示例#1
0
def read(humfile, sonpath, cs2cs_args="epsg:26949", c=1450.0, draft=0.3, doplot=1, t=0.108, bedpick=1, flip_lr=0, model=998, calc_bearing = 0, filt_bearing = 0, chunk='d100'): #cog = 1,

    '''
    Read a .DAT and associated set of .SON files recorded by a Humminbird(R)
    instrument.

    Parse the data into a set of memory mapped files that will
    subsequently be used by the other functions of the PyHum module.

    Export time-series data and metadata in other formats.

    Create a kml file for visualising boat track

    Syntax
    ----------
    [] = PyHum.read(humfile, sonpath, cs2cs_args, c, draft, doplot, t, bedpick, flip_lr, chunksize, model, calc_bearing, filt_bearing, chunk)

    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
    c : float, *optional* [Default=1450.0]
       speed of sound in water (m/s). Defaults to a value of freshwater
    draft : float, *optional* [Default=0.3]
       draft from water surface to transducer face (m)
    doplot : float, *optional* [Default=1]
       if 1, plots will be made
    t : float, *optional* [Default=0.108]
       length of transducer array (m).
       Default value is that of the 998 series Humminbird(R)
    bedpick : int, *optional* [Default=1]
       if 1, bedpicking with be carried out automatically
       if 0, user will be prompted to pick the bed location on screen
    flip_lr : int, *optional* [Default=0]
       if 1, port and starboard scans will be flipped
       (for situations where the transducer is flipped 180 degrees)
    model: int, *optional* [Default=998]
       A 3 or 4 number code indicating the model number
       Examples: 998, 997, 1198, 1199
    calc_bearing : float, *optional* [Default=0]
       if 1, bearing will be calculated from coordinates
    filt_bearing : float, *optional* [Default=0]
       if 1, bearing will be filtered
    chunk : str, *optional* [Default='d100' (distance, 100 m)]
       letter, followed by a number.
       There are the following letter options:
       'd' - parse chunks based on distance, then number which is distance in m
       'p' - parse chunks based on number of pings, then number which is number of pings
       'h' - parse chunks based on change in heading, then number which is the change in heading in degrees
       '1' - process just 1 chunk

    Returns
    ---------
    sonpath+base+'_data_port.dat': memory-mapped file
        contains the raw echogram from the port side
        sidescan sonar (where present)

    sonpath+base+'_data_port.dat': memory-mapped file
        contains the raw echogram from the starboard side
        sidescan sonar (where present)

    sonpath+base+'_data_dwnhi.dat': memory-mapped file
        contains the raw echogram from the high-frequency
        echosounder (where present)

    sonpath+base+'_data_dwnlow.dat': memory-mapped file
        contains the raw echogram from the low-frequency
        echosounder (where present)

    sonpath+base+"trackline.kml": google-earth kml file
        contains the trackline of the vessel during data
        acquisition

    sonpath+base+'rawdat.csv': comma separated value file
        contains time-series data. columns corresponding to
        longitude
        latitude
        easting (m)
        northing (m)
        depth to bed (m)
        alongtrack cumulative distance (m)
        vessel heading (deg.)

    sonpath+base+'meta.mat': .mat file
        matlab format file containing a dictionary object
        holding metadata information. Fields are:
        e : ndarray, easting (m)
        n : ndarray, northing (m)
        es : ndarray, low-pass filtered easting (m)
        ns : ndarray, low-pass filtered northing (m)
        lat : ndarray, latitude
        lon : ndarray, longitude
        shape_port : tuple, shape of port scans in memory mapped file
        shape_star : tuple, shape of starboard scans in memory mapped file
        shape_hi : tuple, shape of high-freq. scans in memory mapped file
        shape_low : tuple, shape of low-freq. scans in memory mapped file
        dep_m : ndarray, depth to bed (m)
        dist_m : ndarray, distance along track (m)
        heading : ndarray, heading of vessel (deg. N)
        pix_m: float, size of 1 pixel in across-track dimension (m)
        bed : ndarray, depth to bed (m)
        c : float, speed of sound in water (m/s)
        t : length of sidescan transducer array (m)
        spd : ndarray, vessel speed (m/s)
        time_s : ndarray, time elapsed (s)
        caltime : ndarray, unix epoch time (s)
    '''

    # 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 'Son files are in %s' % (sonpath)

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

    if draft:
      draft = float(draft)
      print 'Draft: %s' % (str(draft))

    if c:
      c = float(c)
      print 'Celerity of sound: %s m/s' % (str(c))

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

    if flip_lr:
      flip_lr = int(flip_lr)
      if flip_lr==1:
         print "Port and starboard will be flipped"

    if t:
      t = np.asarray(t,float)
      print 'Transducer length is %s m' % (str(t))

    if bedpick:
      bedpick = np.asarray(bedpick,int)
      if bedpick==1:
         print 'Bed picking is auto'
      elif bedpick==0:
         print 'Bed picking is manual'
      else:
         print 'User will be prompted per chunk about bed picking method'

    if chunk:
       chunk = str(chunk)
       if chunk[0]=='d':
          chunkmode=1
          chunkval = int(chunk[1:])
          print 'Chunks based on distance of %s m' % (str(chunkval))
       elif chunk[0]=='p':
          chunkmode=2
          chunkval = int(chunk[1:])
          print 'Chunks based on %s pings' % (str(chunkval))
       elif chunk[0]=='h':
          chunkmode=3
          chunkval = int(chunk[1:])
          print 'Chunks based on heading devation of %s degrees' % (str(chunkval))
       elif chunk[0]=='1':
          chunkmode=4
          chunkval = 1
          print 'Only 1 chunk will be produced'
       else:
          print "Chunk mode not understood - should be 'd', 'p', or 'h' - using defaults"
          chunkmode=1
          chunkval = 100
          print 'Chunks based on distance of %s m' % (str(chunkval))

    if model:
       model = int(model)
       print "Data is from the %s series"  % (str(model))

#    if cog:
#       cog = int(cog)
#       if cog==1:
#          print "Heading based on course-over-ground"

    if calc_bearing:
       calc_bearing = int(calc_bearing)
       if calc_bearing==1:
          print "Bearing will be calculated from coordinates"

    if filt_bearing:
       filt_bearing = int(filt_bearing)
       if filt_bearing==1:
          print "Bearing will be filtered"

    ## for debugging
    #humfile = r"test.DAT"; sonpath = "test_data"
    #cs2cs_args = "epsg:26949"; doplot = 1; draft = 0
    #c=1450; bedpick=1; fliplr=1; chunk = 'd100'
    #model=998; cog=1; calc_bearing=0; filt_bearing=0

    f = 455

    try:
       print "Checking the epsg code you have chosen for compatibility with Basemap ... "
       from mpl_toolkits.basemap import Basemap
       m = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
          resolution = 'i', llcrnrlon=10, llcrnrlat=10, urcrnrlon=30, urcrnrlat=30)
       del m
       print "... epsg code compatible"
    except:
       print "Error: the epsg code you have chosen is not compatible with Basemap"
       print "please choose a different epsg code (http://spatialreference.org/)"
       print "program will now close"
       sys.exit()

    # 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

    # get the SON files from this directory
    sonfiles = glob.glob(sonpath+'*.SON')
    if not sonfiles:
        sonfiles = glob.glob(os.getcwd()+os.sep+sonpath+'*.SON')

    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)

    print "WARNING: Because files have to be read in byte by byte,"
    print "this could take a very long time ..."

    #reading each sonfile in parallel should be faster ...
    try:
       o = Parallel(n_jobs = np.min([len(sonfiles), cpu_count()]), verbose=0)(delayed(getscans)(sonfiles[k], humfile, c, model, cs2cs_args) for k in xrange(len(sonfiles)))
       X, Y, A, B = zip(*o)

       for k in xrange(len(Y)):
          if Y[k] == 'sidescan_port':
             dat = A[k] #data.gethumdat()
             metadat = B[k] #data.getmetadata()
             if flip_lr==0:
                data_port = X[k].astype('int16')
             else:
                data_star = X[k].astype('int16')

          elif Y[k] == 'sidescan_starboard':
             if flip_lr==0:
                data_star = X[k].astype('int16')
             else:
                data_port = X[k].astype('int16')

          elif Y[k] == 'down_lowfreq':
             data_dwnlow = X[k].astype('int16')

          elif Y[k] == 'down_highfreq':
             data_dwnhi = X[k].astype('int16')

       del X, Y, A, B, o
       old_pyread = 0

       if 'data_port' not in locals():
          data_port = ''
          print "portside scan not available"

       if 'data_star' not in locals():
          data_star = ''
          print "starboardside scan not available"

       if 'data_dwnhi' not in locals():
          data_dwnlow = ''
          print "high-frq. downward scan not available"

       if 'data_dwnlow' not in locals():
          data_dwnlow = ''
          print "low-frq. downward scan not available"

    except: # revert back to older version if paralleleised version fails

       print "something went wrong with the parallelised version of pyread ..."

       import pyread
       data = pyread.pyread(sonfiles, humfile, c, model, cs2cs_args)

       dat = data.gethumdat()

       metadat = data.getmetadata()

       old_pyread = 1

    nrec = len(metadat['n'])

    metadat['instr_heading'] = metadat['heading'][:nrec]

    #metadat['heading'] = humutils.get_bearing(calc_bearing, filt_bearing, cog, metadat['lat'], metadat['lon'], metadat['instr_heading'])

    try:
       es = humutils.runningMeanFast(metadat['e'][:nrec],len(metadat['e'][:nrec])/100)
       ns = humutils.runningMeanFast(metadat['n'][:nrec],len(metadat['n'][:nrec])/100)
    except:
       es = metadat['e'][:nrec]
       ns = metadat['n'][:nrec]

    metadat['es'] = es
    metadat['ns'] = ns

    try:
       trans =  pyproj.Proj(init=cs2cs_args)
    except:
       trans =  pyproj.Proj(cs2cs_args.lstrip(), inverse=True)

    lon, lat = trans(es, ns, inverse=True)
    metadat['lon'] = lon
    metadat['lat'] = lat

    metadat['heading'] = humutils.get_bearing(calc_bearing, filt_bearing, metadat['lat'], metadat['lon'], metadat['instr_heading']) #cog

    dist_m = humutils.get_dist(lat, lon)
    metadat['dist_m'] = dist_m

    if calc_bearing==1: # recalculate speed, m/s
       ds=np.gradient(np.squeeze(metadat['time_s']))
       dx=np.gradient(np.squeeze(metadat['dist_m']))
       metadat['spd'] = dx[:nrec]/ds[:nrec]

    # theta at 3dB in the horizontal
    theta3dB = np.arcsin(c/(t*(f*1000)))
    #resolution of 1 sidescan pixel to nadir
    ft = (np.pi/2)*(1/theta3dB) #/ (f/455)

    dep_m = humutils.get_depth(metadat['dep_m'][:nrec])

    if old_pyread == 1: #older pyread version

       # port scan
       try:
          if flip_lr==0:
             data_port = data.getportscans().astype('int16')
          else:
             data_port = data.getstarscans().astype('int16')
       except:
          data_port = ''
          print "portside scan not available"

    if data_port!='':

       Zt, ind_port = makechunks_scan(chunkmode, chunkval, metadat, data_port, 0)
       del data_port

       ## create memory mapped file for Z
       shape_port = io.set_mmap_data(sonpath, base, '_data_port.dat', 'int16', Zt)

       ##we are only going to access the portion of memory required
       port_fp = io.get_mmap_data(sonpath, base, '_data_port.dat', 'int16', shape_port)

    if old_pyread == 1: #older pyread version
       # starboard scan
       try:
          if flip_lr==0:
             data_star = data.getstarscans().astype('int16')
          else:
             data_star = data.getportscans().astype('int16')
       except:
          data_star = ''
          print "starboardside scan not available"

    if data_star!='':

       Zt, ind_star = makechunks_scan(chunkmode, chunkval, metadat, data_star, 1)
       del data_star

       # create memory mapped file for Z
       shape_star = io.set_mmap_data(sonpath, base, '_data_star.dat', 'int16', Zt)

       star_fp = io.get_mmap_data(sonpath, base, '_data_star.dat', 'int16', shape_star)

    if 'star_fp' in locals() and 'port_fp' in locals():
       # check that port and starboard are same size
       # and trim if not
       if np.shape(star_fp)!=np.shape(port_fp):
          print "port and starboard scans are different sizes ... rectifying"
          if np.shape(port_fp[0])[1] > np.shape(star_fp[0])[1]:
             tmp = port_fp.copy()
             tmp2 = np.empty_like(star_fp)
             for k in xrange(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(star_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_port = io.set_mmap_data(sonpath, base, '_data_port2.dat', 'int16', tmp2)
             #shape_star = shape_port.copy()
             shape_star = tuple(np.asarray(shape_port).copy())

             ##we are only going to access the portion of memory required
             port_fp = io.get_mmap_data(sonpath, base, '_data_port2.dat', 'int16', shape_port)

             ind_port = list(ind_port)
             ind_port[-1] = np.shape(star_fp[0])[1]
             ind_port = tuple(ind_port)

          elif np.shape(port_fp[0])[1] < np.shape(star_fp[0])[1]:
             tmp = star_fp.copy()
             tmp2 = np.empty_like(port_fp)
             for k in xrange(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(port_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_port = io.set_mmap_data(sonpath, base, '_data_star2.dat', 'int16', tmp2)
             #shape_star = shape_port.copy()
             shape_star = tuple(np.asarray(shape_port).copy())

             #we are only going to access the portion of memory required
             star_fp = io.get_mmap_data(sonpath, base, '_data_star2.dat', 'int16', shape_star)

             ind_star = list(ind_star)
             ind_star[-1] = np.shape(port_fp[0])[1]
             ind_star = tuple(ind_star)

    if old_pyread == 1: #older pyread version
       # low-freq. sonar
       try:
          data_dwnlow = data.getlowscans().astype('int16')
       except:
          data_dwnlow = ''
          print "low-freq. scan not available"

    if data_dwnlow!='':

       Zt, ind_low = makechunks_scan(chunkmode, chunkval, metadat, data_dwnlow, 2)
       del data_dwnlow

       # create memory mapped file for Z
       shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', Zt)

       ##we are only going to access the portion of memory required
       dwnlow_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', shape_low)

    if old_pyread == 1: #older pyread version
       # hi-freq. sonar
       try:
          data_dwnhi = data.gethiscans().astype('int16')
       except:
          data_dwnhi = ''
          print "high-freq. scan not available"

    if data_dwnhi!='':

       Zt, ind_hi = makechunks_scan(chunkmode, chunkval, metadat, data_dwnhi, 3)
       del data_dwnhi

       # create memory mapped file for Z
       shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', Zt)

       dwnhi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', shape_hi)

    if 'dwnhi_fp' in locals() and 'dwnlow_fp' in locals():
       # check that low and high are same size
       # and trim if not
       if (np.shape(dwnhi_fp)!=np.shape(dwnlow_fp)) and (chunkmode!=4):
          print "dwnhi and dwnlow are different sizes ... rectifying"
          if np.shape(dwnhi_fp[0])[1] > np.shape(dwnlow_fp[0])[1]:
             tmp = dwnhi_fp.copy()
             tmp2 = np.empty_like(dwnlow_fp)
             for k in xrange(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(dwnlow_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_low = io.set_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', tmp2)
             #shape_hi = shape_low.copy()
             shape_hi = tuple(np.asarray(shape_low).copy())

             ##we are only going to access the portion of memory required
             dwnhi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', shape_hi)

             ind_hi = list(ind_hi)
             ind_hi[-1] = np.shape(dwnlow_fp[0])[1]
             ind_hi = tuple(ind_hi)

          elif np.shape(dwnhi_fp[0])[1] < np.shape(dwnlow_fp[0])[1]:
             tmp = dwnlow_fp.copy()
             tmp2 = np.empty_like(dwnhi_fp)
             for k in xrange(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(dwnhi_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', tmp2)
             #shape_hi = shape_low.copy()
             shape_hi = tuple(np.asarray(shape_low).copy())

             ##we are only going to access the portion of memory required
             dwnlow_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', shape_low)

             ind_low = list(ind_low)
             ind_low[-1] = np.shape(dwnhi_fp[0])[1]
             ind_low = tuple(ind_low)

    if old_pyread == 1: #older pyread version
       del data

    if ('shape_port' in locals()) and (chunkmode!=4):
       metadat['shape_port'] = shape_port
       nrec = metadat['shape_port'][0] * metadat['shape_port'][2]
    elif ('shape_port' in locals()) and (chunkmode==4):
       metadat['shape_port'] = shape_port
       nrec = metadat['shape_port'][1]
    else:
       metadat['shape_port'] = ''

    if ('shape_star' in locals()) and (chunkmode!=4):
       metadat['shape_star'] = shape_star
       nrec = metadat['shape_star'][0] * metadat['shape_star'][2]
    elif ('shape_star' in locals()) and (chunkmode==4):
       metadat['shape_star'] = shape_star
       nrec = metadat['shape_star'][1]
    else:
       metadat['shape_star'] = ''

    if ('shape_hi' in locals()) and (chunkmode!=4):
       metadat['shape_hi'] = shape_hi
       #nrec = metadat['shape_hi'][0] * metadat['shape_hi'][2] * 2
    elif ('shape_hi' in locals()) and (chunkmode==4):
       metadat['shape_hi'] = shape_hi
    else:
       metadat['shape_hi'] = ''

    if ('shape_low' in locals()) and (chunkmode!=4):
       metadat['shape_low'] = shape_low
       #nrec = metadat['shape_low'][0] * metadat['shape_low'][2] * 2
    elif ('shape_low' in locals()) and (chunkmode==4):
       metadat['shape_low'] = shape_low
    else:
       metadat['shape_low'] = ''

    #make kml boat trackline
    humutils.make_trackline(lon,lat, sonpath, base)

    if 'port_fp' in locals() and 'star_fp' in locals():

       #if not os.path.isfile(os.path.normpath(os.path.join(sonpath,base+'meta.mat'))):
       if 2>1:
          if bedpick == 1: # auto

             x, bed = humutils.auto_bedpick(ft, dep_m, chunkmode, port_fp, c)

             if len(dist_m)<len(bed):
                dist_m = np.append(dist_m,dist_m[-1]*np.ones(len(bed)-len(dist_m)))

             if doplot==1:
                if chunkmode!=4:
                   for k in xrange(len(star_fp)):
                      plot_2bedpicks(port_fp[k], star_fp[k], bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], x[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
                else:
                   plot_2bedpicks(port_fp, star_fp, bed, dist_m, x, ft, shape_port, sonpath, 0, chunkmode)

             # 'real' bed is estimated to be the minimum of the two
             bed = np.min(np.vstack((bed[:nrec],np.squeeze(x[:nrec]))),axis=0)
             bed = humutils.runningMeanFast(bed, 3)

          elif bedpick>1: # user prompt

             x, bed = humutils.auto_bedpick(ft, dep_m, chunkmode, port_fp, c)

             if len(dist_m)<len(bed):
                dist_m = np.append(dist_m,dist_m[-1]*np.ones(len(bed)-len(dist_m)))

             # 'real' bed is estimated to be the minimum of the two
             bed = np.min(np.vstack((bed[:nrec],np.squeeze(x[:nrec]))),axis=0)
             bed = humutils.runningMeanFast(bed, 3)

             # manually intervene
             fig = plt.figure()
             ax = plt.gca()
             if chunkmode !=4:
                im = ax.imshow(np.hstack(port_fp), cmap = 'gray', origin = 'upper')
             else:
                im = ax.imshow(port_fp, cmap = 'gray', origin = 'upper')
             plt.plot(bed,'r')
             plt.axis('normal'); plt.axis('tight')

             pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
             x1=map(lambda x: x[0],pts1) # map applies the function passed as
             y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
             plt.close()
             del fig

             if x1 != []: # if x1 is not empty
                tree = KDTree(zip(np.arange(1,len(bed)), bed))
                try:
                   dist, inds = tree.query(zip(x1, y1), k = 100, eps=5, n_jobs=-1)
                except:
                   dist, inds = tree.query(zip(x1, y1), k = 100, eps=5)

                b = np.interp(inds,x1,y1)
                bed2 = bed.copy()
                bed2[inds] = b
                bed = bed2

             if doplot==1:
                if chunkmode!=4:
                   for k in xrange(len(star_fp)):
                      plot_2bedpicks(port_fp[k], star_fp[k], bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], x[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
                else:
                   plot_2bedpicks(port_fp, star_fp, bed, dist_m, x, ft, shape_port, sonpath, 0, chunkmode)

          else: #manual

             beds=[]

             if chunkmode!=4:
                for k in xrange(len(port_fp)):
                   raw_input("Bed picking "+str(k+1)+" of "+str(len(port_fp))+", are you ready? 30 seconds. Press Enter to continue...")
                   bed={}
                   fig = plt.figure()
                   ax = plt.gca()
                   im = ax.imshow(port_fp[k], cmap = 'gray', origin = 'upper')
                   pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
                   x1=map(lambda x: x[0],pts1) # map applies the function passed as
                   y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
                   bed = np.interp(np.r_[:ind_port[-1]],x1,y1)
                   plt.close()
                   del fig
                   beds.append(bed)
                   extent = np.shape(port_fp[k])[0]
                bed = np.asarray(np.hstack(beds),'float')
             else:
                raw_input("Bed picking - are you ready? 30 seconds. Press Enter to continue...")
                bed={}
                fig = plt.figure()
                ax = plt.gca()
                im = ax.imshow(port_fp, cmap = 'gray', origin = 'upper')
                pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
                x1=map(lambda x: x[0],pts1) # map applies the function passed as
                y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
                bed = np.interp(np.r_[:ind_port[-1]],x1,y1)
                plt.close()
                del fig
                beds.append(bed)
                extent = np.shape(port_fp)[1]
                bed = np.asarray(np.hstack(beds),'float')

          # now revise the depth in metres
          dep_m = (1/ft)*bed

          if doplot==1:
             if chunkmode!=4:
                for k in xrange(len(star_fp)):
                   plot_bedpick(port_fp[k], star_fp[k], (1/ft)*bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
             else:
                plot_bedpick(port_fp, star_fp, (1/ft)*bed, dist_m, ft, shape_port, sonpath, 0, chunkmode)

          metadat['bed'] = bed[:nrec]

    else:
       metadat['bed'] = dep_m[:nrec]*ft

    metadat['heading'] = metadat['heading'][:nrec]
    metadat['lon'] = lon[:nrec]
    metadat['lat'] = lat[:nrec]
    metadat['dist_m'] = dist_m[:nrec]
    metadat['dep_m'] = dep_m[:nrec]
    metadat['pix_m'] = 1/ft
    metadat['bed'] = metadat['bed'][:nrec]
    metadat['c'] = c
    metadat['t'] = t
    metadat['f'] = f

    metadat['spd'] = metadat['spd'][:nrec]
    metadat['time_s'] = metadat['time_s'][:nrec]
    metadat['e'] = metadat['e'][:nrec]
    metadat['n'] = metadat['n'][:nrec]
    metadat['es'] = metadat['es'][:nrec]
    metadat['ns'] = metadat['ns'][:nrec]
    metadat['caltime'] = metadat['caltime'][:nrec]

    savemat(os.path.normpath(os.path.join(sonpath,base+'meta.mat')), metadat ,oned_as='row')

    f = open(os.path.normpath(os.path.join(sonpath,base+'rawdat.csv')), 'wt')
    writer = csv.writer(f)
    writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth (m)', 'distance (m)', 'instr. heading (deg)', 'heading (deg.)' ) )
    for i in range(0, nrec):
       writer.writerow(( float(lon[i]),float(lat[i]),float(es[i]),float(ns[i]),float(dep_m[i]),float(dist_m[i]), float(metadat['instr_heading'][i]), float(metadat['heading'][i]) ))
    f.close()

    del lat, lon, dep_m #, dist_m

    if doplot==1:

       plot_pos(sonpath, metadat, es, ns)

       if 'dwnlow_fp' in locals():

          plot_dwnlow(dwnlow_fp, chunkmode, sonpath)

       if 'dwnhi_fp' in locals():

          plot_dwnhi(dwnhi_fp, chunkmode, sonpath)

    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!"
示例#2
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!"
示例#3
0
def e1e2(humfile, sonpath, cs2cs_args, ph, temp, salinity, beam, transfreq, integ, numclusters, doplot):
         
    '''
    Analysis of first (e1, 'roughness') and second (e2, 'hardness') echo returns from the high-frequency downward looking echosounder
    Generates generalised acoustic parameters
    for the purposes of point classification of submerged substrates/vegetation
    Accounts for the absorption of sound in water
    Does a basic k-means cluster of e1 and e2 coefficients into specified number of 'acoustic classes'
    based on code by Barb Fagetter ([email protected])

    Syntax
    ----------
    [] = PyHum.e1e2(humfile, sonpath, cs2cs_args, ph, temp, salinity, beam, transfreq, integ, numclusters, doplot)

    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

    ph : float, *optional* [Default=7.0]
       water acidity in pH

    temp : float, *optional* [Default=10.0]
       water temperature in degrees Celsius

    salinity : float, *optional* [Default=0.0]
       salinity of water in parts per thousand

    beam : float, *optional* [Default=20.0]
       beam width in degrees

    transfreq : float, *optional* [Default=200.0]
       transducer frequency in kHz

    integ : int, *optional* [Default=5]
       number of pings over which to integrate

    numclusters : int, *optional* [Default=3]
       number of acoustic classes to classify all the data into

    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    Returns
    -------
    sonpath+base+'rough_and_hard'+str(p)+'.csv'  : csv file
        contains the following fields: 'longitude', 'latitude', 'easting', 'northing', 'depth', 
        'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label'
        of the pth chunk
        'average' implies average over 'integ' successive pings

    The following are returned if doplot==1:

    sonpath+'e1e2_scan'+str(p).png : png image file
       png image file showing the downward echosounder echogram overlain with the locations of the start and 
       end of the first and second echo region envelope 

    sonpath+'e1e2_kmeans'+str(p).png: png image file
        png image file showing 1) (left) volume scattering coefficient 1 versus volume scattering coefficient 2, colour-coded
        by k-means acoustic class, and
        2) (right) e1 versus e2, colour-coded
        by k-means acoustic class

    sonpath+'rgh_hard_kmeans'+str(p).png : png image file
        png image file showing scatter plot of easting versus northing colour-coded by k-means acoustic class 

    sonpath+'map_rgh'+str(p).png : png image file
        png image file showing scatter plot of 'roughness' (e1) overlying an aerial image pulled from an ESRI image server 

    sonpath+'map_hard'+str(p).png : png image file
        png image file showing scatter plot of 'hardness' (e2) overlying an aerial image pulled from an ESRI image server 

    sonpath,'Rough'+str(p).png : png image file 
        png image overlay associated with the kml file, sonpath,'Hard'+str(p).kml

    sonpath,'Rough'+str(p).kml : kml file
        kml overlay for showing roughness scatter plot (sonpath,'Rough'+str(p).png)

    sonpath,'Hard'+str(p).png : png image file
        png image overlay associated with the kml file, sonpath,'Hard'+str(p).kml
    
    sonpath,'Hard'+str(p).kml : kml file
        kml overlay for showing harness scatter plot (sonpath,'Hard'+str(p).png)

    '''

    # 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
       inputfile = 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 beam:
       beam = np.asarray(beam,float)
       print('Beam is %s deg' % (str(beam)))

    if salinity:
       salinity = np.asarray(salinity,float)
       print('Salinity is %s ppt' % (str(salinity)))

    if ph:
       ph = np.asarray(ph,float)
       print('pH is %s' % (str(ph)))

    if temp:
       temp = np.asarray(temp,float)
       print('Temperature is %s' % (str(temp)))

    if transfreq:
       transfreq = np.asarray(transfreq,float)
       print('Dwnward sonar freq. is %s' % (str(transfreq)))

    if integ:
       integ = np.asarray(integ,int)
       print('number of records for integration is %s' % (str(integ)))

    if numclusters:
       numclusters = np.asarray(numclusters,int)
       print('number of returned acoustic clusters is %s' % (str(numclusters)))

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


    # 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')))

    beamwidth = beam*(np.sqrt(0.5))
    equivbeam = (5.78/(np.power(1.6,2)))*(np.power((np.sin((beamwidth*np.pi)/(2*180))),2))

    meta = loadmat(sonpath+base+'meta.mat')

    c = np.squeeze(meta['c'])
    t = np.squeeze(meta['t'])
    f = np.squeeze(meta['f'])
    maxW = np.squeeze(meta['maxW'])

    lat = np.squeeze(meta['lat'])
    lon = np.squeeze(meta['lon'])
    es = np.squeeze(meta['e'])
    ns = np.squeeze(meta['n'])
    dep = np.squeeze(meta['dep_m'])
    #del meta

    # load memory mapped scans
    shape_hi= np.squeeze(meta['shape_hi'])
    if shape_hi!='':
       try:
          #dwnhi_fp = np.memmap(sonpath+base+'_data_dwnhi.dat', dtype='int16', mode='r', shape=tuple(shape_hi))
          with open(os.path.normpath(os.path.join(sonpath,base+'_data_dwnhi.dat')), 'r') as ff:
             dwnhi_fp = np.memmap(ff, dtype='int16', mode='r', shape=tuple(shape_hi))

       except:
          shape_lo= np.squeeze(meta['shape_low'])
          #dwnhi_fp = np.memmap(sonpath+base+'_data_dwnhi.dat', dtype='int16', mode='r', shape=tuple(shape_lo))
          with open(os.path.normpath(os.path.join(sonpath,base+'_data_dwnhi.dat')), 'r') as ff:
             dwnhi_fp = np.memmap(ff, dtype='int16', mode='r', shape=tuple(shape_lo))
    

    if 'dwnhi_fp' in locals():

       theta3dB = np.arcsin(c/(t*(f*1000))) # *(180/pi) # to see in degs
       ft = (np.pi/2)*(1/theta3dB)
       bed = ft*dep

       if len(shape_hi)>2:    
          i = np.linspace(1,shape_hi[0]*shape_hi[2], len(bed)) 
          #np.shape(beam_data)[1],len(bed))
          #bedi = np.interp(np.linspace(1,np.shape(beam_data)[1],np.shape(beam_data)[1]), i, bed)
          bedi = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, bed)  
          ei = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, es)    
          ni = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, ns)    
          lati = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, lat)   
          loni = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, lon)    
          del i
       else:
          i = np.linspace(1,shape_hi[1], len(bed)) 
          #np.shape(beam_data)[1],len(bed))
          #bedi = np.interp(np.linspace(1,np.shape(beam_data)[1],np.shape(beam_data)[1]), i, bed)
          bedi = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, bed)  
          ei = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, es)    
          ni = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, ns)    
          lati = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, lat)   
          loni = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, lon)    
          del i 
          
       bedi = np.asarray(bedi,'int')

       depi = ((1/ft)*bedi) 

       # near-field region
       nf = int(ft*(1000*(0.105**2)*f/(4*1500)))

       #absorption = calcAb(c, ph, salinity, temp, np.asarray(depi), transfreq)
       absorption = water_atten(np.asarray(depi), transfreq, c, ph, temp, salinity)

       if len(shape_hi)>2:    
          for p in range(len(dwnhi_fp)):
             #make an index of every other record
             ind = range(0,np.shape(dwnhi_fp[p])[1])

             Zdepi = depi[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zabsorp = absorption[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zlat = lati[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zlon = loni[shape_hi[2]*p:shape_hi[2]*(p+1)]       
             Zes = ei[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zns = ni[shape_hi[2]*p:shape_hi[2]*(p+1)]       
                
             try: #parallel processing with all available cores
               w = Parallel(n_jobs=-1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[p][:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)
             except: #fall back to serial
               w = Parallel(n_jobs=1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[p][:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)

             rough, hard, sv_e1, sv_e2, e1a, e1b, e2a, e2b = zip(*w) 

             rough = np.array(rough,'float')
             rough[rough==0.0] = np.nan

             hard = np.array(hard,'float')
             hard[hard==0.0] = np.nan

             sv_e1 = np.array(sv_e1,'float')
             sv_e1[sv_e1==0.0] = np.nan

             sv_e2 = np.array(sv_e2,'float')
             sv_e2[sv_e2==0.0] = np.nan

             try:
                nans, y= humutils.nan_helper(rough)
                rough[nans]= np.interp(y(nans), y(~nans), rough[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(hard)
                hard[nans]= np.interp(y(nans), y(~nans), hard[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e1)
                sv_e1[nans]= np.interp(y(nans), y(~nans), sv_e1[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e2)
                sv_e2[nans]= np.interp(y(nans), y(~nans), sv_e2[~nans])
             except:
                pass

             data = np.column_stack([sv_e1, sv_e2])
             k_means = MiniBatchKMeans(numclusters)
             # fit the model
             k_means.fit(data) 
             values = k_means.cluster_centers_.squeeze()
             labels = k_means.labels_
    
             hardav = humutils.runningMeanFast(hard,integ)
             roughav = humutils.runningMeanFast(rough,integ)

             #f = open(sonpath+base+'rough_and_hard'+str(p)+'.csv', 'wt')
             f = open(os.path.normpath(os.path.join(sonpath,base+'rough_and_hard'+str(p)+'.csv')), 'wt')
             writer = csv.writer(f)
             writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth', 'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label') )
             for i in range(0, len(rough)):
                writer.writerow(( float(Zlon[i]),float(Zlat[i]),float(Zes[i]),float(Zns[i]),float(Zdepi[i]),float(rough[i]),float(hard[i]),float(roughav[i]),float(hardav[i]), labels[i].astype(int) ))
             f.close()

             if doplot==1:
                try:

                   fig = plt.figure()
                   plt.imshow(dwnhi_fp[p], cmap='gray')
                   plt.plot(e1a,'r');
                   plt.plot(e1b,'y');
                   plt.plot(e2a,'c');
                   plt.plot(e2b,'m');
                   plt.axis('tight')
                   #plt.show()
                   custom_save(sonpath,'e1e2_scan'+str(p))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   fig = plt.figure()
                   fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   plt.subplot(221)   
                   plt.plot(sv_e1[labels==0],sv_e2[labels==0],'ko');
                   plt.plot(sv_e1[labels==1],sv_e2[labels==1],'ro');
                   plt.plot(sv_e1[labels==2],sv_e2[labels==2],'bo');
                   plt.xlabel('SV1'); plt.ylabel('SV2')
                   plt.xlim(0,1); plt.ylim(0,1)

                   plt.subplot(222)   
                   plt.plot(rough[labels==0],hard[labels==0],'ko');
                   plt.plot(rough[labels==1],hard[labels==1],'ro');
                   plt.plot(rough[labels==2],hard[labels==2],'bo');
                   plt.xlabel('E1'); plt.ylabel('E2')
                   plt.xlim(1,8); plt.ylim(1,8)
                   #plt.show()
                   custom_save(sonpath,'e1e2_kmeans'+str(p))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   fig = plt.figure()
                   s=plt.scatter(Zes[labels==0],Zns[labels==0],marker='o',c='k', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==1],Zns[labels==1],marker='o',c='r', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==2],Zns[labels==2],marker='o',c='b', s=10, linewidth=0, vmin=0, vmax=8);
                   custom_save(sonpath,'rgh_hard_kmeans'+str(p))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   print("drawing and printing map ...")
                   fig = plt.figure(frameon=False)
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1], #epsg=26949,
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)                   

                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E1')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_rgh'+str(p))
                   del fig 

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:
                   fig = plt.figure()
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)
                      
                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E2')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_hard'+str(p))
                   del fig 

                except:
                   print("plot could not be produced")

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Rough'+str(p))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Rough'+str(p)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Rough'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Rough'+str(p)+'.kml')))

                except:
                   print("plot could not be produced")

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Hard'+str(p))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Hard'+str(p)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Hard'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Hard'+str(p)+'.kml')))

                except:
                   print("plot could not be produced")

       else:
          if 2 > 1: # need to tiday all this up later!!
             #make an index of every other record
             ind = range(0,np.shape(dwnhi_fp)[1])

             Zdepi = depi
             Zabsorp = absorption
             Zlat = lati
             Zlon = loni       
             Zes = ei
             Zns = ni      
                
             try: #parallel processing with all available cores
               w = Parallel(n_jobs=-1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)
             except: #fall back to serial
               w = Parallel(n_jobs=1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)

             rough, hard, sv_e1, sv_e2, e1a, e1b, e2a, e2b = zip(*w) 

             rough = np.array(rough,'float')
             rough[rough==0.0] = np.nan

             hard = np.array(hard,'float')
             hard[hard==0.0] = np.nan

             sv_e1 = np.array(sv_e1,'float')
             sv_e1[sv_e1==0.0] = np.nan

             sv_e2 = np.array(sv_e2,'float')
             sv_e2[sv_e2==0.0] = np.nan

             try:
                nans, y= humutils.nan_helper(rough)
                rough[nans]= np.interp(y(nans), y(~nans), rough[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(hard)
                hard[nans]= np.interp(y(nans), y(~nans), hard[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e1)
                sv_e1[nans]= np.interp(y(nans), y(~nans), sv_e1[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e2)
                sv_e2[nans]= np.interp(y(nans), y(~nans), sv_e2[~nans])
             except:
                pass

             data = np.column_stack([sv_e1, sv_e2])
             k_means = MiniBatchKMeans(numclusters)
             # fit the model
             k_means.fit(data) 
             values = k_means.cluster_centers_.squeeze()
             labels = k_means.labels_
    
             hardav = humutils.runningMeanFast(hard,integ)
             roughav = humutils.runningMeanFast(rough,integ)

             #f = open(sonpath+base+'rough_and_hard'+str(p)+'.csv', 'wt')
             f = open(os.path.normpath(os.path.join(sonpath,base+'rough_and_hard'+str(0)+'.csv')), 'wt')
             writer = csv.writer(f)
             writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth', 'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label') )
             for i in range(0, len(rough)):
                writer.writerow(( float(Zlon[i]),float(Zlat[i]),float(Zes[i]),float(Zns[i]),float(Zdepi[i]),float(rough[i]),float(hard[i]),float(roughav[i]),float(hardav[i]), labels[i].astype(int) ))
             f.close()

             if doplot==1:
                try:

                   fig = plt.figure()
                   plt.imshow(dwnhi_fp, cmap='gray')
                   plt.plot(e1a,'r');
                   plt.plot(e1b,'y');
                   plt.plot(e2a,'c');
                   plt.plot(e2b,'m');
                   plt.axis('tight')
                   #plt.show()
                   custom_save(sonpath,'e1e2_scan'+str(0))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   fig = plt.figure()
                   fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   plt.subplot(221)   
                   plt.plot(sv_e1[labels==0],sv_e2[labels==0],'ko');
                   plt.plot(sv_e1[labels==1],sv_e2[labels==1],'ro');
                   plt.plot(sv_e1[labels==2],sv_e2[labels==2],'bo');
                   plt.xlabel('SV1'); plt.ylabel('SV2')
                   plt.xlim(0,1); plt.ylim(0,1)

                   plt.subplot(222)   
                   plt.plot(rough[labels==0],hard[labels==0],'ko');
                   plt.plot(rough[labels==1],hard[labels==1],'ro');
                   plt.plot(rough[labels==2],hard[labels==2],'bo');
                   plt.xlabel('E1'); plt.ylabel('E2')
                   plt.xlim(1,8); plt.ylim(1,8)
                   #plt.show()
                   custom_save(sonpath,'e1e2_kmeans'+str(0))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   fig = plt.figure()
                   s=plt.scatter(Zes[labels==0],Zns[labels==0],marker='o',c='k', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==1],Zns[labels==1],marker='o',c='r', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==2],Zns[labels==2],marker='o',c='b', s=10, linewidth=0, vmin=0, vmax=8);
                   custom_save(sonpath,'rgh_hard_kmeans'+str(0))
                   del fig

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:

                   print("drawing and printing map ...")
                   fig = plt.figure(frameon=False)
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1], #epsg=26949,
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)
  
                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E1')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_rgh'+str(0))
                   del fig 

                except:
                   print("plot could not be produced")

             if doplot==1:
                try:
                   fig = plt.figure()
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)

                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E2')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_hard'+str(0))
                   del fig 

                except:
                   print("plot could not be produced")

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Rough'+str(0))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Rough'+str(0)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Rough'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Rough'+str(0)+'.kml')))

                except:
                   print("plot could not be produced")

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Hard'+str(0))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Hard'+str(0)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Hard'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Hard'+str(0)+'.kml')))

                except:
                   print("plot could not be produced")     

    else:
       print("high-frequency downward echosounder data not available")
def texture_slic(humfile, sonpath, doplot=1, 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, doplot, numclasses, maxscale, notes)

      Parameters
      ----------
      humfile : str
       path to the .DAT file
      sonpath : str
       path where the *.SON files are
      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
      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 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]

      #work on the entire scan
      #im = humutils.rescale(np.vstack((np.flipud(np.hstack(port_fp)), np.hstack(star_fp))),0,1)
      im = np.vstack((np.flipud(np.hstack(port_fp)), np.hstack(star_fp)))
      im[np.isnan(im)] = 0
      im = humutils.rescale(im,0,1)

      #get SLIC superpixels
      segments_slic = slic(im, n_segments=int(im.shape[0]/10), compactness=.1)

      #pre-allocate texture lengthscale array
      tl = np.zeros(im.shape, dtype = "float64")

      #cycle through each segment and compute tl
      for k in np.unique(segments_slic):
         mask = np.zeros(im.shape[:2], dtype = "uint8")
         mask[segments_slic == k] = 255
         cmask, cim = crop_toseg(mask, im)
         tl[segments_slic == k] = parallel_me(cim, maxscale, notes, np.shape(cim)[0])

      R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32', tuple(shape_star))
      R = np.vstack((np.flipud(np.hstack(R_fp)), np.hstack(R_fp)))
      R = R/np.max(R)

      #correct for range and scale
      tl = tl * np.cos(R) * (1/ft)
      tl[im==0] = np.nan 
      tl[np.isnan(im)] = np.nan 

      # 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))

      counter = 0
      if len(shape_star)>2:
         for p in range(len(port_fp)):
            if p==0:
               n,m = np.shape(np.vstack((np.flipud(port_fp[p]), star_fp[p])))
            else:
               n,m = np.shape(np.vstack((np.flipud(port_fp[p]), star_fp[p])))
            Sp = tl[:n, counter:counter+m]
            counter = counter+m
            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:

            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)

      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, 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!")
示例#5
0
def map_texture(humfile, sonpath, cs2cs_args = "epsg:26949", res = 0.5, mode=3, nn = 64, numstdevs=5): #influence = 10, 
         
    '''
    Create plots of the texture lengthscale maps made in PyHum.texture module 
    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.map_texture(humfile, sonpath, cs2cs_args, res, mode, nn, numstdevs)

    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.5]
       grid resolution of output gridded texture map
    mode: int, *optional* [Default=3]
       gridding mode. 1 = nearest neighbour
                      2 = inverse weighted nearest neighbour
                      3 = Gaussian weighted nearest neighbour
    nn: int, *optional* [Default=64]
       number of nearest neighbours for gridding (used if mode > 1) 
    numstdevs: int, *optional* [Default = 4]
       Threshold number of standard deviations in texture lengthscale per grid cell up to which to accept 
           
    Returns
    -------
    sonpath+'x_y_class'+str(p)+'.asc' : text file
        contains the point cloud of easting, northing, and texture lengthscales
        of the pth chunk

    sonpath+'class_GroundOverlay'+str(p)+'.kml': kml file
        contains gridded (or point cloud) texture lengthscale map for importing into google earth
        of the pth chunk

    sonpath+'class_map'+str(p)+'.png' : 
        image overlay associated with the kml file

    sonpath+'class_map_imagery'+str(p)+'.png' : png image file
        gridded (or point cloud) texture lengthscale map
        overlain onto an image pulled from esri image server

    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 cs2cs_args:
       print 'cs2cs arguments are %s' % (cs2cs_args)

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

    if mode:
       mode = int(mode)
       print 'Mode for gridding: %s' % (str(mode))      

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

    #if influence:
    #   influence = int(influence)
    #   print 'Radius of influence for gridding: %s (m)' % (str(influence))             

    if numstdevs:
       numstdevs = int(numstdevs)
       print 'Threshold number of standard deviations in texture lengthscale per grid cell up to which to accept: %s' % (str(numstdevs))             

    # 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']) 

    pix_m = np.squeeze(meta['pix_m'])
    dep_m = np.squeeze(meta['dep_m'])
    c = np.squeeze(meta['c'])
    #dist_m = np.squeeze(meta['dist_m'])

    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))

    if len(shape_star)>2:    
       shape = shape_port.copy()
       shape[1] = shape_port[1] + shape_star[1]
       class_fp = io.get_mmap_data(sonpath, base, '_data_class.dat', 'float32', tuple(shape))
       #with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'r') as ff:
       #   class_fp = np.memmap(ff, dtype='float32', mode='r', shape=tuple(shape))
    else:
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'r') as ff:
          class_fp = np.load(ff)    


    tvg = ((8.5*10**-5)+(3/76923)+((8.5*10**-5)/4))*c
    dist_tvg = ((np.tan(np.radians(25)))*dep_m)-(tvg)

    if len(shape_star)>2:    
       for p in xrange(len(class_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)]

          len_n = len(n)
   
          merge = class_fp[p].copy()

          merge[np.isnan(merge)] = 0
          merge[np.isnan(np.vstack((np.flipud(port_fp[p]),star_fp[p])))] = 0

          extent = shape_port[1]
          R1 = merge[extent:,:]
          R2 = np.flipud(merge[:extent,:])

          merge = np.vstack((R2,R1))
          del R1, R2

          # get number pixels in scan line
          extent = int(np.shape(merge)[0]/2)

          yvec = np.linspace(pix_m,extent*pix_m,extent)

          X, Y  = getXY(e,n,yvec,d,t,extent)

          merge[merge==0] = np.nan

          if len(merge.flatten()) != len(X):
             merge = merge[:,:len_n]

          merge = merge.T.flatten()

          index = np.where(np.logical_not(np.isnan(merge)))[0]

          X, Y, merge = trim_xys(X, Y, merge, index)

          X = X.astype('float32')
          Y = Y.astype('float32')
          merge = merge.astype('float32')
          
          # write raw bs to file
          outfile = os.path.normpath(os.path.join(sonpath,'x_y_class'+str(p)+'.asc'))
          with open(outfile, 'w') as f:
             np.savetxt(f, np.hstack((humutils.ascol(X),humutils.ascol(Y), humutils.ascol(merge))), delimiter=' ', fmt="%8.6f %8.6f %8.6f")

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

          #if dogrid==1:

          orig_def, targ_def, grid_x, grid_y, res, shape = get_griddefs(np.min(X), np.max(X), np.min(Y), np.max(Y), res, humlon, humlat, trans)

          grid_x = grid_x.astype('float32')
          grid_y = grid_y.astype('float32')
                                      
          sigmas = 1 #m
          eps = 2
          dat, res = get_grid(mode, orig_def, targ_def, merge, res*10, np.min(X), np.max(X), np.min(Y), np.max(Y), res, nn, sigmas, eps, shape, numstdevs, trans, humlon, humlat)
          
          del merge
             
          dat[dat==0] = np.nan
          dat[np.isinf(dat)] = np.nan

          datm = np.ma.masked_invalid(dat)
          del dat

          glon, glat = trans(grid_x, grid_y, inverse=True)
          del grid_x, grid_y
          
          vmin=np.nanmin(datm)+0.1
          vmax=np.nanmax(datm)-0.1
          if vmin > vmax:
             vmin=np.nanmin(datm)
             vmax=np.nanmax(datm)            
          
          print_map(cs2cs_args, glon, glat, datm, sonpath, p, vmin=vmin, vmax=vmax)

    else: #just 1 chunk   
    
       e = esi
       n = nsi
       t = theta
       d = dist_tvg

       len_n = len(n)
   
       merge = class_fp.copy()

       merge[np.isnan(merge)] = 0
       merge[np.isnan(np.vstack((np.flipud(port_fp),star_fp)))] = 0

       extent = shape_port[0]
       R1 = merge[extent:,:]
       R2 = np.flipud(merge[:extent,:])

       merge = np.vstack((R2,R1))
       del R1, R2

       # get number pixels in scan line
       extent = int(np.shape(merge)[0]/2)

       yvec = np.linspace(pix_m,extent*pix_m,extent)

       X, Y  = getXY(e,n,yvec,d,t,extent)

       merge[merge==0] = np.nan

       if len(merge.flatten()) != len(X):
          merge = merge[:,:len_n]

       merge = merge.T.flatten()

       index = np.where(np.logical_not(np.isnan(merge)))[0]

       X, Y, merge = trim_xys(X, Y, merge, index)

       # write raw bs to file
       outfile = os.path.normpath(os.path.join(sonpath,'x_y_class'+str(0)+'.asc'))
       with open(outfile, 'w') as f:
          np.savetxt(f, np.hstack((humutils.ascol(X),humutils.ascol(Y), humutils.ascol(merge))), delimiter=' ', fmt="%8.6f %8.6f %8.6f")

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

       #if dogrid==1:
       if 2>1:

          orig_def, targ_def, grid_x, grid_y, res, shape = get_griddefs(np.min(X), np.max(X), np.min(Y), np.max(Y), res, humlon, humlat, trans)

          ## create mask for where the data is not
          tree = KDTree(np.c_[X.flatten(),Y.flatten()])

          if pykdtree==1:
             dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1)                      
          else:
             try:
                dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1, n_jobs=cpu_count())
             except:
                #print ".... update your scipy installation to use faster kd-tree queries"
                dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1)

          dist = dist.reshape(grid_x.shape)
             
          sigmas = 1 #m
          eps = 2
          dat, res = get_grid(mode, orig_def, targ_def, merge, res*10, np.min(X), np.max(X), np.min(Y), np.max(Y), res, nn, sigmas, eps, shape, numstdevs, trans, humlon, humlat)
          
          del merge

       #if dogrid==1:
       if 2>1:
          dat[dat==0] = np.nan
          dat[np.isinf(dat)] = np.nan
          dat[dist>res*2] = np.nan
          del dist

          datm = np.ma.masked_invalid(dat)

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

       vmin=np.nanmin(datm)+0.1
       vmax=np.nanmax(datm)-0.1
       if vmin > vmax:
         vmin=np.nanmin(datm)
         vmax=np.nanmax(datm)
       
       Parallel(n_jobs = 2, verbose=0)(delayed(doplots)(k, humlon, humlat, cs2cs_args, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax) for k in xrange(2)) 
       
       #print_map(cs2cs_args, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax)

       #print_contour_map(cs2cs_args, humlon, humlat, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax) 

    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!"
示例#6
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("===================================================")
示例#7
0
def rmshadows(humfile, sonpath, win=31, shadowmask=0, doplot=1):
    '''
    Remove dark shadows in scans caused by shallows, shorelines, and attenuation of acoustics with distance
    Manual or automated processing options available
    Works on the radiometrically corrected outputs of the correct module

    Syntax
    ----------
    [] = PyHum.rmshadows(humfile, sonpath, win, shadowmask, doplot)

    Parameters
    ----------
    humfile : str
       path to the .DAT file
    sonpath : str
       path where the *.SON files are
    win : int, *optional* [Default=100]
       window size (pixels) for the automated shadow removal algorithm
    shadowmask : int, *optional* [Default=0]
       1 = do manual shadow masking, otherwise do automatic shadow masking
    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    Returns
    -------
    sonpath+base+'_data_star_la.dat': memory-mapped file
        contains the starboard scan with water column removed and 
        radiometrically corrected, and shadows removed

    sonpath+base+'_data_port_la.dat': memory-mapped file
        contains the portside scan with water column removed and
        radiometrically corrected, and shadows removed

    '''

    # 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 shadowmask:
        shadowmask = np.asarray(shadowmask, int)
        if shadowmask == 1:
            print 'Shadow masking is manual'
        else:
            print 'Shadow masking is auto'

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

    # 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]

    base = humutils.strip_base(base)

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

    # load memory mapped scans
    shape_port = np.squeeze(meta['shape_port'])
    if shape_port != '':
        #port_fp = np.memmap(sonpath+base+'_data_port_la.dat', dtype='float32', mode='r', shape=tuple(shape_port))
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_la.dat')),
                'r') as ff:
            port_fp = np.memmap(ff,
                                dtype='float32',
                                mode='r',
                                shape=tuple(shape_port))

    shape_star = np.squeeze(meta['shape_star'])
    if shape_star != '':
        #star_fp = np.memmap(sonpath+base+'_data_star_la.dat', dtype='float32', mode='r', shape=tuple(shape_star))
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_la.dat')),
                'r') as ff:
            star_fp = np.memmap(ff,
                                dtype='float32',
                                mode='r',
                                shape=tuple(shape_star))

    dist_m = np.squeeze(meta['dist_m'])
    ft = 1 / (meta['pix_m'])
    extent = shape_star[1]

    if shadowmask == 1:  #manual

        Zt = []
        if len(np.shape(star_fp)) > 2:
            for p in xrange(len(star_fp)):
                raw_input(
                    "Shore picking (starboard), are you ready? 30 seconds. Press Enter to continue..."
                )
                shoreline_star = {}
                fig = plt.figure()
                ax = plt.gca()
                ax.imshow(star_fp[p], cmap='gray')  #, origin = 'upper') #im =
                plt.axis('normal')
                plt.axis('tight')
                pts1 = plt.ginput(
                    n=300,
                    timeout=30)  # it will wait for 200 clicks or 30 seconds
                x1 = map(lambda x: x[0],
                         pts1)  # map applies the function passed as
                y1 = map(lambda x: x[1],
                         pts1)  # first parameter to each element of pts
                shoreline_star = np.interp(np.r_[:np.shape(star_fp[p])[1]], x1,
                                           y1)
                plt.close()
                del fig

                star_mg = star_fp[p].copy()

                shoreline_star = np.asarray(shoreline_star, 'int')
                # shift proportionally depending on where the bed is
                for k in xrange(np.shape(star_mg)[1]):
                    star_mg[shoreline_star[k]:, k] = np.nan

                del shoreline_star

                Zt.append(star_mg)

        else:

            raw_input(
                "Shore picking (starboard), are you ready? 30 seconds. Press Enter to continue..."
            )
            shoreline_star = {}
            fig = plt.figure()
            ax = plt.gca()
            ax.imshow(star_fp, cmap='gray')  #, origin = 'upper') #im =
            plt.axis('normal')
            plt.axis('tight')
            pts1 = plt.ginput(
                n=300, timeout=30)  # it will wait for 200 clicks or 30 seconds
            x1 = map(lambda x: x[0],
                     pts1)  # map applies the function passed as
            y1 = map(lambda x: x[1],
                     pts1)  # first parameter to each element of pts
            shoreline_star = np.interp(np.r_[:np.shape(star_fp)[1]], x1, y1)
            plt.close()
            del fig

            star_mg = star_fp.copy()

            shoreline_star = np.asarray(shoreline_star, 'int')
            # shift proportionally depending on where the bed is
            for k in xrange(np.shape(star_mg)[1]):
                star_mg[shoreline_star[k]:, k] = np.nan

            del shoreline_star

            Zt.append(star_mg)

        ## create memory mapped file for Z
        #p = np.memmap(sonpath+base+'_data_star_la.dat', dtype='float32', mode='w+', shape=np.shape(Zt))
        #fp[:] = Zt[:]
        #del fp

        Zt = np.squeeze(Zt)

        # create memory mapped file for Zs
        #fp = np.memmap(sonpath+base+'_data_star_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zs))
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_lar.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zt))
        fp[:] = Zt[:]
        del fp
        del Zt

        #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_star_la.dat')))

        Zt = []
        if len(np.shape(star_fp)) > 2:
            for p in xrange(len(port_fp)):

                raw_input(
                    "Shore picking (port), are you ready? 30 seconds. Press Enter to continue..."
                )
                shoreline_port = {}
                fig = plt.figure()
                ax = plt.gca()
                ax.imshow(port_fp[p], cmap='gray')  #, origin = 'upper') #im =
                plt.axis('normal')
                plt.axis('tight')
                pts1 = plt.ginput(
                    n=300,
                    timeout=30)  # it will wait for 200 clicks or 30 seconds
                x1 = map(lambda x: x[0],
                         pts1)  # map applies the function passed as
                y1 = map(lambda x: x[1],
                         pts1)  # first parameter to each element of pts
                shoreline_port = np.interp(np.r_[:np.shape(port_fp[p])[1]], x1,
                                           y1)
                plt.close()
                del fig

                port_mg = port_fp[p].copy()

                shoreline_port = np.asarray(shoreline_port, 'int')
                # shift proportionally depending on where the bed is
                for k in xrange(np.shape(port_mg)[1]):
                    port_mg[shoreline_port[k]:, k] = np.nan

                del shoreline_port

                Zt.append(port_mg)

        else:

            raw_input(
                "Shore picking (port), are you ready? 30 seconds. Press Enter to continue..."
            )
            shoreline_port = {}
            fig = plt.figure()
            ax = plt.gca()
            ax.imshow(port_fp, cmap='gray')  #, origin = 'upper') #im =
            plt.axis('normal')
            plt.axis('tight')
            pts1 = plt.ginput(
                n=300, timeout=30)  # it will wait for 200 clicks or 30 seconds
            x1 = map(lambda x: x[0],
                     pts1)  # map applies the function passed as
            y1 = map(lambda x: x[1],
                     pts1)  # first parameter to each element of pts
            shoreline_port = np.interp(np.r_[:np.shape(port_fp)[1]], x1, y1)
            plt.close()
            del fig

            port_mg = port_fp.copy()

            shoreline_port = np.asarray(shoreline_port, 'int')
            # shift proportionally depending on where the bed is
            for k in xrange(np.shape(port_mg)[1]):
                port_mg[shoreline_port[k]:, k] = np.nan

            del shoreline_port

            Zt.append(port_mg)

        Zt = np.squeeze(Zt)
        ## create memory mapped file for Z
        #fp = np.memmap(sonpath+base+'_data_port_la.dat', dtype='float32', mode='w+', shape=np.shape(Zt))
        #fp[:] = Zt[:]
        #del fp

        # create memory mapped file for Zp
        #fp = np.memmap(sonpath+base+'_data_port_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zp))
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_lar.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zt))
        fp[:] = Zt[:]
        del fp
        del Zt

        #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_port_la.dat')))

    else:  #auto

        #win = 31

        Zs = []
        Zp = []
        if len(np.shape(star_fp)) > 2:
            for p in xrange(len(star_fp)):
                merge = np.vstack((np.flipud(port_fp[p]), star_fp[p]))
                merge = np.asarray(merge, 'float64')

                merge_mask = np.vstack((np.flipud(port_fp[p]), star_fp[p]))

                merge[merge_mask == 0] = 0
                del merge_mask

                mask = np.asarray(merge != 0,
                                  'int8')  # only 8bit precision needed

                merge[np.isnan(merge)] = 0

                #Z,ind = humutils.sliding_window(merge,(win,win),(win/2,win/2))
                Z, ind = humutils.sliding_window(merge, (win, win), (win, win))

                #zmean = np.reshape(zmean, ( ind[0], ind[1] ) )
                Ny, Nx = np.shape(merge)
                #zmean[np.isnan(zmean)] = 0

                try:  #parallel processing with all available cores
                    w = Parallel(n_jobs=-1,
                                 verbose=0)(delayed(parallel_me)(Z[k])
                                            for k in xrange(len(Z)))
                except:  #fall back to serial
                    w = Parallel(n_jobs=1,
                                 verbose=0)(delayed(parallel_me)(Z[k])
                                            for k in xrange(len(Z)))

                zmean = np.reshape(w, (ind[0], ind[1]))
                del w

                M = humutils.im_resize(zmean, Nx, Ny)
                M[mask == 0] = 0
                del zmean

                bw = M > 0.5
                del M

                # erode and dilate to remove splotches of no data
                bw2 = binary_dilation(binary_erosion(bw,
                                                     structure=np.ones(
                                                         (3, 3))),
                                      structure=np.ones((13, 13)))
                #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win/4,win/4))), structure=np.ones((win/4,win/4)))
                ##bw2 = binary_erosion(bw,structure=np.ones((win*2,win*2)))

                ## fill holes
                bw2 = binary_fill_holes(bw2, structure=np.ones(
                    (win, win))).astype(int)
                merge2 = grey_erosion(merge, structure=np.ones((win, win)))

                #del bw
                #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

                bw2 = np.asarray(bw != 0,
                                 'int8')  # we only need 8 bit precision
                del bw

                merge[bw2 == 1] = 0  #blank out bad data
                merge[merge2 == np.min(merge2)] = 0  #blank out bad data
                del merge2

                ## do plots of merged scans
                if doplot == 1:

                    Zdist = dist_m[shape_port[-1] * p:shape_port[-1] * (p + 1)]

                    fig = plt.figure()
                    plt.imshow(merge,
                               cmap='gray',
                               extent=[
                                   min(Zdist),
                                   max(Zdist), -extent * (1 / ft),
                                   extent * (1 / ft)
                               ])
                    plt.ylabel('Range (m)'), plt.xlabel(
                        'Distance along track (m)')

                    plt.axis('normal')
                    plt.axis('tight')
                    custom_save(sonpath,
                                'merge_corrected_rmshadow_scan' + str(p))
                    del fig

                Zp.append(np.flipud(merge[:shape_port[1], :]))
                Zs.append(merge[shape_port[1]:, :])
                del merge, bw2

        else:

            merge = np.vstack((np.flipud(port_fp), star_fp))
            merge = np.asarray(merge, 'float64')

            merge_mask = np.vstack((np.flipud(port_fp), star_fp))

            merge[merge_mask == 0] = 0
            del merge_mask

            mask = np.asarray(merge != 0, 'int8')  # only 8bit precision needed

            merge[np.isnan(merge)] = 0

            #Z,ind = humutils.sliding_window(merge,(win,win),(win/2,win/2))
            Z, ind = humutils.sliding_window(merge, (win, win), (win, win))

            #zmean = np.reshape(zmean, ( ind[0], ind[1] ) )
            Ny, Nx = np.shape(merge)
            #zmean[np.isnan(zmean)] = 0

            try:  #parallel processing with all available cores
                w = Parallel(n_jobs=-1, verbose=0)(delayed(parallel_me)(Z[k])
                                                   for k in xrange(len(Z)))
            except:  #fall back to serial
                w = Parallel(n_jobs=1, verbose=0)(delayed(parallel_me)(Z[k])
                                                  for k in xrange(len(Z)))

            zmean = np.reshape(w, (ind[0], ind[1]))
            del w

            M = humutils.im_resize(zmean, Nx, Ny)
            M[mask == 0] = 0
            del zmean

            bw = M > 0.5
            del M

            # erode and dilate to remove splotches of no data
            bw2 = binary_dilation(binary_erosion(bw, structure=np.ones(
                (3, 3))),
                                  structure=np.ones((13, 13)))
            #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win/4,win/4))), structure=np.ones((win/4,win/4)))
            ##bw2 = binary_erosion(bw,structure=np.ones((win*2,win*2)))

            ## fill holes
            bw2 = binary_fill_holes(bw2, structure=np.ones(
                (win, win))).astype(int)
            merge2 = grey_erosion(merge, structure=np.ones((win, win)))

            #del bw
            #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

            bw2 = np.asarray(bw != 0, 'int8')  # we only need 8 bit precision
            del bw

            merge[bw2 == 1] = 0  #blank out bad data
            merge[merge2 == np.min(merge2)] = 0  #blank out bad data
            del merge2

            # erode and dilate to remove splotches of no data
            #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((3,3))), structure=np.ones((13,13)))
            #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win,win))), structure=np.ones((win*2,win*2)))
            #bw2 = binary_erosion(bw,structure=np.ones((win,win)))

            # fill holes
            #bw2 = binary_fill_holes(bw2, structure=np.ones((3,3))).astype(int)
            #del bw
            #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

            #merge[bw2==1] = 0 #blank out bad data

            ## do plots of merged scans
            if doplot == 1:

                Zdist = dist_m
                fig = plt.figure()
                plt.imshow(merge,
                           cmap='gray',
                           extent=[
                               min(Zdist),
                               max(Zdist), -extent * (1 / ft),
                               extent * (1 / ft)
                           ])
                plt.ylabel('Range (m)'), plt.xlabel('Distance along track (m)')

                plt.axis('normal')
                plt.axis('tight')
                custom_save(sonpath, 'merge_corrected_rmshadow_scan' + str(0))
                del fig

            Zp.append(np.flipud(merge[:shape_port[0], :]))
            Zs.append(merge[shape_port[0]:, :])
            del merge, bw2

        Zp = np.squeeze(Zp)
        Zs = np.squeeze(Zs)
        # create memory mapped file for Zp
        #fp = np.memmap(sonpath+base+'_data_port_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zp))
        #with open(sonpath+base+'_data_port_lar.dat', 'w+') as f:
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_port_lar.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zp))
        fp[:] = Zp[:]
        del fp
        del Zp

        #shutil.move(sonpath+base+'_data_port_lar.dat', sonpath+base+'_data_port_la.dat')
        #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_port_la.dat')))

        # create memory mapped file for Zs
        #fp = np.memmap(sonpath+base+'_data_star_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zs))
        #with open(sonpath+base+'_data_star_lar.dat', 'w+') as f:
        with open(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_star_lar.dat')),
                'w+') as ff:
            fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zs))
        fp[:] = Zs[:]
        del fp
        del Zs

        #shutil.move(sonpath+base+'_data_star_lar.dat', sonpath+base+'_data_star_la.dat')
        #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_star_la.dat')))

    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!"
示例#8
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!")
示例#9
0
def rmshadows(humfile, sonpath, win, shadowmask, doplot, dissim, correl, contrast, energy, mn):
    '''
    Remove dark shadows in scans caused by shallows, shorelines, and attenuation of acoustics with distance
    Manual or automated processing options available
    Works on the radiometrically corrected outputs of the correct module

    Syntax
    ----------
    [] = PyHum.rmshadows(humfile, sonpath, win, shadowmask, doplot)

    Parameters
    ----------
    humfile : str
       path to the .DAT file
    sonpath : str
       path where the *.SON files are
    win : int, *optional* [Default=100]
       window size (pixels) for the automated shadow removal algorithm
    shadowmask : int, *optional* [Default=0]
       1 = do manual shadow masking, otherwise do automatic shadow masking
    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    Returns
    -------
    sonpath+base+'_data_star_la.dat': memory-mapped file
        contains the starboard scan with water column removed and 
        radiometrically corrected, and shadows removed

    sonpath+base+'_data_port_la.dat': memory-mapped file
        contains the portside scan with water column removed and
        radiometrically corrected, and shadows removed

    '''

    # 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 shadowmask:
       shadowmask = np.asarray(shadowmask,int)
       if shadowmask==1:
          print('Shadow masking is manual')
       else: 
          print('Shadow masking is auto')
          
    if doplot:
       doplot = int(doplot)
       if doplot==0:
          print("Plots will not be made")

    if dissim:
       dissim = np.asarray(dissim,int)
       print('Threshold dissimilarity (shadow is <) is %s' % (str(dissim)))

    if correl:
       correl = np.asarray(correl,int)
       print('Threshold correlation (shadow is <) is %s' % (str(correl)))

    if contrast:
       contrast = np.asarray(contrast,int)
       print('Threshold contrast (shadow is <) is %s' % (str(contrast)))

    if energy:
       energy = np.asarray(energy,int)
       print('Threshold energy (shadow is >) is %s' % (str(energy)))

    if mn:
       mn = np.asarray(mn,int)
       print('Threshold mean intensity (shadow is <) is %s' % (str(mn)))

    # 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]

    base = humutils.strip_base(base)

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

    # load memory mapped scans
    shape_port = np.squeeze(meta['shape_port'])
    if shape_port!='':
       #port_fp = np.memmap(sonpath+base+'_data_port_la.dat', dtype='float32', mode='r', shape=tuple(shape_port))
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_port_la.dat')), 'r') as ff:
          port_fp = np.memmap(ff, dtype='float32', mode='r', shape=tuple(shape_port))

    shape_star = np.squeeze(meta['shape_star'])
    if shape_star!='':
       #star_fp = np.memmap(sonpath+base+'_data_star_la.dat', dtype='float32', mode='r', shape=tuple(shape_star))
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_star_la.dat')), 'r') as ff:
          star_fp = np.memmap(ff, dtype='float32', mode='r', shape=tuple(shape_star))

    dist_m = np.squeeze(meta['dist_m'])
    ft = 1/(meta['pix_m'])
    extent = shape_star[1] 

    if shadowmask==1: #manual

       Zt = []
       if len(np.shape(star_fp))>2:
          for p in range(len(star_fp)):
             raw_input("Shore picking "+str(p+1)+" of "+str(len(star_fp))+" (starboard), are you ready? 60 seconds. Press Enter to continue...")
             shoreline_star={}
             fig = plt.figure()
             ax = plt.gca()
             ax.imshow(star_fp[p], cmap = 'gray') #, origin = 'upper') #im = 
             plt.axis('normal'); plt.axis('tight')
             pts1 = plt.ginput(n=300, timeout=75) # it will wait for 200 clicks or 75 seconds
             x1=map(lambda x: x[0],pts1) # map applies the function passed as 
             y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
             shoreline_star = np.interp(np.r_[:np.shape(star_fp[p])[1]],x1,y1)
             plt.close()
             del fig

             star_mg = star_fp[p].copy()
             
             shoreline_star = np.asarray(shoreline_star,'int')
             # shift proportionally depending on where the bed is
             for k in range(np.shape(star_mg)[1]):
                star_mg[shoreline_star[k]:,k] = np.nan

             del shoreline_star

             Zt.append(star_mg)
             
       else:

          raw_input("Shore picking "+str(len(star_fp))+" of "+str(len(star_fp))+" (starboard), are you ready? 60 seconds. Press Enter to continue...")
          shoreline_star={}
          fig = plt.figure()
          ax = plt.gca()
          ax.imshow(star_fp, cmap = 'gray') #, origin = 'upper') #im = 
          plt.axis('normal'); plt.axis('tight')
          pts1 = plt.ginput(n=300, timeout=75) # it will wait for 200 clicks or 75 seconds
          x1=map(lambda x: x[0],pts1) # map applies the function passed as 
          y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
          shoreline_star = np.interp(np.r_[:np.shape(star_fp)[1]],x1,y1)
          plt.close()
          del fig

          star_mg = star_fp.copy()

          shoreline_star = np.asarray(shoreline_star,'int')
          # shift proportionally depending on where the bed is
          for k in range(np.shape(star_mg)[1]):
             star_mg[shoreline_star[k]:,k] = np.nan

          del shoreline_star

          Zt.append(star_mg)

       ## create memory mapped file for Z
       #p = np.memmap(sonpath+base+'_data_star_la.dat', dtype='float32', mode='w+', shape=np.shape(Zt))
       #fp[:] = Zt[:]
       #del fp

       Zt = np.squeeze(Zt)
             
       # create memory mapped file for Zs
       #fp = np.memmap(sonpath+base+'_data_star_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zs))
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), 'w+') as ff:
          fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zt))
       fp[:] = Zt[:]
       del fp
       del Zt

       #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_star_la.dat')))


       Zt = []
       if len(np.shape(star_fp))>2:
          for p in range(len(port_fp)):

             raw_input("Shore picking "+str(p+1)+" of "+str(len(port_fp))+" (port), are you ready? 60 seconds. Press Enter to continue...")
             shoreline_port={}
             fig = plt.figure()
             ax = plt.gca()
             ax.imshow(port_fp[p], cmap = 'gray') #, origin = 'upper') #im = 
             plt.axis('normal'); plt.axis('tight')
             pts1 = plt.ginput(n=300, timeout=75) # it will wait for 200 clicks or 75 seconds
             x1=map(lambda x: x[0],pts1) # map applies the function passed as 
             y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
             shoreline_port = np.interp(np.r_[:np.shape(port_fp[p])[1]],x1,y1)
             plt.close()
             del fig

             port_mg = port_fp[p].copy()

             shoreline_port = np.asarray(shoreline_port,'int')
             # shift proportionally depending on where the bed is
             for k in range(np.shape(port_mg)[1]):
                port_mg[shoreline_port[k]:,k] = np.nan

             del shoreline_port

             Zt.append(port_mg)
          
       else:

          raw_input("Shore picking "+str(len(port_fp))+" of "+str(len(port_fp))+" (port), are you ready? 60 seconds. Press Enter to continue...")
          shoreline_port={}
          fig = plt.figure()
          ax = plt.gca()
          ax.imshow(port_fp, cmap = 'gray') #, origin = 'upper') #im = 
          plt.axis('normal'); plt.axis('tight')
          pts1 = plt.ginput(n=300, timeout=75) # it will wait for 200 clicks or 75 seconds
          x1=map(lambda x: x[0],pts1) # map applies the function passed as 
          y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
          shoreline_port = np.interp(np.r_[:np.shape(port_fp)[1]],x1,y1)
          plt.close()
          del fig

          port_mg = port_fp.copy()

          shoreline_port = np.asarray(shoreline_port,'int')
          # shift proportionally depending on where the bed is
          for k in range(np.shape(port_mg)[1]):
             port_mg[shoreline_port[k]:,k] = np.nan

          del shoreline_port

          Zt.append(port_mg)

       Zt = np.squeeze(Zt)
       ## create memory mapped file for Z
       #fp = np.memmap(sonpath+base+'_data_port_la.dat', dtype='float32', mode='w+', shape=np.shape(Zt))
       #fp[:] = Zt[:]
       #del fp

       # create memory mapped file for Zp
       #fp = np.memmap(sonpath+base+'_data_port_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zp))
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), 'w+') as ff:
          fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zt))
       fp[:] = Zt[:]
       del fp
       del Zt    

       #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_port_la.dat')))

    else: #auto

       Zs = []; Zp = []
       if len(np.shape(star_fp))>2:
          for p in range(len(star_fp)):
             merge = np.vstack((np.flipud(port_fp[p]),star_fp[p]))
             merge = np.asarray(merge, 'float64')

             merge_mask = np.vstack((np.flipud(port_fp[p]),star_fp[p]))

             merge[merge_mask==0] = 0
             del merge_mask

             mask = np.asarray(merge!=0,'int8') # only 8bit precision needed

             merge[np.isnan(merge)] = 0

             #Z,ind = humutils.sliding_window(merge,(win,win),(win/2,win/2))
             Z,ind = humutils.sliding_window(merge,(win,win),(win,win))

             #zmean = np.reshape(zmean, ( ind[0], ind[1] ) )
             Ny, Nx = np.shape(merge)
             #zmean[np.isnan(zmean)] = 0
          
             try: #parallel processing with all available cores     
                w = Parallel(n_jobs = -1, verbose=0)(delayed(parallel_me)(Z[k], dissim, correl, contrast, energy, mn) for k in range(len(Z)))
             except: #fall back to serial
                w = Parallel(n_jobs = 1, verbose=0)(delayed(parallel_me)(Z[k], dissim, correl, contrast, energy, mn) for k in range(len(Z)))          
          
             zmean = np.reshape(w , ( ind[0], ind[1] ) )
             del w
        
             M = humutils.im_resize(zmean,Nx,Ny)
             M[mask==0] = 0
             del zmean

             bw = M>0.5  
             del M

             # erode and dilate to remove splotches of no data
             bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((3,3))), structure=np.ones((13,13)))             
             #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win/4,win/4))), structure=np.ones((win/4,win/4)))
             ##bw2 = binary_erosion(bw,structure=np.ones((win*2,win*2)))
                         
             ## fill holes
             bw2 = binary_fill_holes(bw2, structure=np.ones((win,win))).astype(int)
             merge2 = grey_erosion(merge,structure=np.ones((win,win)))
                
             #del bw
             #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

             bw2 = np.asarray(bw!=0,'int8') # we only need 8 bit precision
             del bw

             merge[bw2==1] = 0 #blank out bad data
             merge[merge2==np.min(merge2)] = 0 #blank out bad data
             del merge2
         
             ## do plots of merged scans
             if doplot==1:

                Zdist = dist_m[shape_port[-1]*p:shape_port[-1]*(p+1)]

                fig = plt.figure()
                plt.imshow(merge, cmap='gray', extent=[min(Zdist), max(Zdist), -extent*(1/ft), extent*(1/ft)])
                plt.ylabel('Range (m)'), plt.xlabel('Distance along track (m)')

                plt.axis('normal'); plt.axis('tight')
                custom_save(sonpath,'merge_corrected_rmshadow_scan'+str(p))
                del fig

             Zp.append(np.flipud(merge[:shape_port[1],:]))
             Zs.append(merge[shape_port[1]:,:])
             del merge, bw2

       else:

          merge = np.vstack((np.flipud(port_fp),star_fp))
          merge = np.asarray(merge, 'float64')

          merge_mask = np.vstack((np.flipud(port_fp),star_fp))

          merge[merge_mask==0] = 0
          del merge_mask

          mask = np.asarray(merge!=0,'int8') # only 8bit precision needed

          merge[np.isnan(merge)] = 0

          #Z,ind = humutils.sliding_window(merge,(win,win),(win/2,win/2))
          Z,ind = humutils.sliding_window(merge,(win,win),(win,win))

          #zmean = np.reshape(zmean, ( ind[0], ind[1] ) )
          Ny, Nx = np.shape(merge)
          #zmean[np.isnan(zmean)] = 0
          
          try: #parallel processing with all available cores     
             w = Parallel(n_jobs = -1, verbose=0)(delayed(parallel_me)(Z[k], dissim, correl, contrast, energy, mn) for k in range(len(Z)))
          except: #fall back to serial
             w = Parallel(n_jobs = 1, verbose=0)(delayed(parallel_me)(Z[k], dissim, correl, contrast, energy, mn) for k in range(len(Z)))          
          
          zmean = np.reshape(w , ( ind[0], ind[1] ) )
          del w
        
          M = humutils.im_resize(zmean,Nx,Ny)
          M[mask==0] = 0
          del zmean

          bw = M>0.5  
          del M

          # erode and dilate to remove splotches of no data
          bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((3,3))), structure=np.ones((13,13)))             
          #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win/4,win/4))), structure=np.ones((win/4,win/4)))
          ##bw2 = binary_erosion(bw,structure=np.ones((win*2,win*2)))
                         
          ## fill holes
          bw2 = binary_fill_holes(bw2, structure=np.ones((win,win))).astype(int)
          merge2 = grey_erosion(merge,structure=np.ones((win,win)))
                
          #del bw
          #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

          bw2 = np.asarray(bw!=0,'int8') # we only need 8 bit precision
          del bw

          merge[bw2==1] = 0 #blank out bad data
          merge[merge2==np.min(merge2)] = 0 #blank out bad data
          del merge2

          # erode and dilate to remove splotches of no data
          #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((3,3))), structure=np.ones((13,13)))
          #bw2 = binary_dilation(binary_erosion(bw,structure=np.ones((win,win))), structure=np.ones((win*2,win*2)))
          #bw2 = binary_erosion(bw,structure=np.ones((win,win)))
                       
          # fill holes
          #bw2 = binary_fill_holes(bw2, structure=np.ones((3,3))).astype(int)
          #del bw
          #bw2 = np.asarray(bw2!=0,'int8') # we only need 8 bit precision

          #merge[bw2==1] = 0 #blank out bad data
         
          ## do plots of merged scans
          if doplot==1:

             Zdist = dist_m
             fig = plt.figure()
             plt.imshow(merge, cmap='gray', extent=[min(Zdist), max(Zdist), -extent*(1/ft), extent*(1/ft)])
             plt.ylabel('Range (m)'), plt.xlabel('Distance along track (m)')

             plt.axis('normal'); plt.axis('tight')
             custom_save(sonpath,'merge_corrected_rmshadow_scan'+str(0))
             del fig

          Zp.append(np.flipud(merge[:shape_port[0],:]))
          Zs.append(merge[shape_port[0]:,:])
          del merge, bw2

       Zp = np.squeeze(Zp)
       Zs = np.squeeze(Zs)
       # create memory mapped file for Zp
       #fp = np.memmap(sonpath+base+'_data_port_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zp))
       #with open(sonpath+base+'_data_port_lar.dat', 'w+') as f:
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), 'w+') as ff:
          fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zp))
       fp[:] = Zp[:]
       del fp
       del Zp    

       #shutil.move(sonpath+base+'_data_port_lar.dat', sonpath+base+'_data_port_la.dat')
       #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_port_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_port_la.dat')))

       # create memory mapped file for Zs
       #fp = np.memmap(sonpath+base+'_data_star_lar.dat', dtype='float32', mode='w+', shape=np.shape(Zs))
       #with open(sonpath+base+'_data_star_lar.dat', 'w+') as f:
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), 'w+') as ff:
          fp = np.memmap(ff, dtype='float32', mode='w+', shape=np.shape(Zs))
       fp[:] = Zs[:]
       del fp
       del Zs

       #shutil.move(sonpath+base+'_data_star_lar.dat', sonpath+base+'_data_star_la.dat')
       #shutil.move(os.path.normpath(os.path.join(sonpath,base+'_data_star_lar.dat')), os.path.normpath(os.path.join(sonpath,base+'_data_star_la.dat')))

    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("===================================================")
示例#10
0
def e1e2(humfile, sonpath, cs2cs_args="epsg:26949", ph=7.0, temp=10.0, salinity=0.0, beam=20.0, transfreq=200.0, integ=5, numclusters=3, doplot=1):
         
    '''
    Analysis of first (e1, 'roughness') and second (e2, 'hardness') echo returns from the high-frequency downward looking echosounder
    Generates generalised acoustic parameters
    for the purposes of point classification of submerged substrates/vegetation
    Accounts for the absorption of sound in water
    Does a basic k-means cluster of e1 and e2 coefficients into specified number of 'acoustic classes'
    based on code by Barb Fagetter ([email protected])

    Syntax
    ----------
    [] = PyHum.e1e2(humfile, sonpath, cs2cs_args, ph, temp, salinity, beam, transfreq, integ, numclusters, doplot)

    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

    ph : float, *optional* [Default=7.0]
       water acidity in pH

    temp : float, *optional* [Default=10.0]
       water temperature in degrees Celsius

    salinity : float, *optional* [Default=0.0]
       salinity of water in parts per thousand

    beam : float, *optional* [Default=20.0]
       beam width in degrees

    transfreq : float, *optional* [Default=200.0]
       transducer frequency in kHz

    integ : int, *optional* [Default=5]
       number of pings over which to integrate

    numclusters : int, *optional* [Default=3]
       number of acoustic classes to classify all the data into

    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    Returns
    -------
    sonpath+base+'rough_and_hard'+str(p)+'.csv'  : csv file
        contains the following fields: 'longitude', 'latitude', 'easting', 'northing', 'depth', 
        'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label'
        of the pth chunk
        'average' implies average over 'integ' successive pings

    The following are returned if doplot==1:

    sonpath+'e1e2_scan'+str(p).png : png image file
       png image file showing the downward echosounder echogram overlain with the locations of the start and 
       end of the first and second echo region envelope 

    sonpath+'e1e2_kmeans'+str(p).png: png image file
        png image file showing 1) (left) volume scattering coefficient 1 versus volume scattering coefficient 2, colour-coded
        by k-means acoustic class, and
        2) (right) e1 versus e2, colour-coded
        by k-means acoustic class

    sonpath+'rgh_hard_kmeans'+str(p).png : png image file
        png image file showing scatter plot of easting versus northing colour-coded by k-means acoustic class 

    sonpath+'map_rgh'+str(p).png : png image file
        png image file showing scatter plot of 'roughness' (e1) overlying an aerial image pulled from an ESRI image server 

    sonpath+'map_hard'+str(p).png : png image file
        png image file showing scatter plot of 'hardness' (e2) overlying an aerial image pulled from an ESRI image server 

    sonpath,'Rough'+str(p).png : png image file 
        png image overlay associated with the kml file, sonpath,'Hard'+str(p).kml

    sonpath,'Rough'+str(p).kml : kml file
        kml overlay for showing roughness scatter plot (sonpath,'Rough'+str(p).png)

    sonpath,'Hard'+str(p).png : png image file
        png image overlay associated with the kml file, sonpath,'Hard'+str(p).kml
    
    sonpath,'Hard'+str(p).kml : kml file
        kml overlay for showing harness scatter plot (sonpath,'Hard'+str(p).png)

    '''

    # 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
       inputfile = 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 beam:
       beam = np.asarray(beam,float)
       print 'Beam is %s deg' % (str(beam))

    if salinity:
       salinity = np.asarray(salinity,float)
       print 'Salinity is %s ppt' % (str(salinity))

    if ph:
       ph = np.asarray(ph,float)
       print 'pH is %s' % (str(ph))

    if temp:
       temp = np.asarray(temp,float)
       print 'Temperature is %s' % (str(temp))

    if transfreq:
       transfreq = np.asarray(transfreq,float)
       print 'Dwnward sonar freq. is %s' % (str(transfreq))

    if integ:
       integ = np.asarray(integ,int)
       print 'number of records for integration is %s' % (str(integ))

    if numclusters:
       numclusters = np.asarray(numclusters,int)
       print 'number of returned acoustic clusters is %s' % (str(numclusters))

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


    # 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')))

    beamwidth = beam*(np.sqrt(0.5))
    equivbeam = (5.78/(np.power(1.6,2)))*(np.power((np.sin((beamwidth*np.pi)/(2*180))),2))

    meta = loadmat(sonpath+base+'meta.mat')

    c = np.squeeze(meta['c'])
    t = np.squeeze(meta['t'])
    f = np.squeeze(meta['f'])
    maxW = np.squeeze(meta['maxW'])

    lat = np.squeeze(meta['lat'])
    lon = np.squeeze(meta['lon'])
    es = np.squeeze(meta['e'])
    ns = np.squeeze(meta['n'])
    dep = np.squeeze(meta['dep_m'])
    #del meta

    # load memory mapped scans
    shape_hi= np.squeeze(meta['shape_hi'])
    if shape_hi!='':
       try:
          #dwnhi_fp = np.memmap(sonpath+base+'_data_dwnhi.dat', dtype='int16', mode='r', shape=tuple(shape_hi))
          with open(os.path.normpath(os.path.join(sonpath,base+'_data_dwnhi.dat')), 'r') as ff:
             dwnhi_fp = np.memmap(ff, dtype='int16', mode='r', shape=tuple(shape_hi))

       except:
          shape_lo= np.squeeze(meta['shape_low'])
          #dwnhi_fp = np.memmap(sonpath+base+'_data_dwnhi.dat', dtype='int16', mode='r', shape=tuple(shape_lo))
          with open(os.path.normpath(os.path.join(sonpath,base+'_data_dwnhi.dat')), 'r') as ff:
             dwnhi_fp = np.memmap(ff, dtype='int16', mode='r', shape=tuple(shape_lo))
    

    if 'dwnhi_fp' in locals():

       theta3dB = np.arcsin(c/(t*(f*1000))) # *(180/pi) # to see in degs
       ft = (np.pi/2)*(1/theta3dB)
       bed = ft*dep

       if len(shape_hi)>2:    
          i = np.linspace(1,shape_hi[0]*shape_hi[2], len(bed)) 
          #np.shape(beam_data)[1],len(bed))
          #bedi = np.interp(np.linspace(1,np.shape(beam_data)[1],np.shape(beam_data)[1]), i, bed)
          bedi = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, bed)  
          ei = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, es)    
          ni = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, ns)    
          lati = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, lat)   
          loni = np.interp(np.linspace(1,shape_hi[0]*shape_hi[2],shape_hi[0]*shape_hi[2]), i, lon)    
          del i
       else:
          i = np.linspace(1,shape_hi[1], len(bed)) 
          #np.shape(beam_data)[1],len(bed))
          #bedi = np.interp(np.linspace(1,np.shape(beam_data)[1],np.shape(beam_data)[1]), i, bed)
          bedi = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, bed)  
          ei = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, es)    
          ni = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, ns)    
          lati = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, lat)   
          loni = np.interp(np.linspace(1,shape_hi[1],shape_hi[1]), i, lon)    
          del i 
          
       bedi = np.asarray(bedi,'int')

       depi = ((1/ft)*bedi) 

       # near-field region
       nf = int(ft*(1000*(0.105**2)*f/(4*1500)))

       #absorption = calcAb(c, ph, salinity, temp, np.asarray(depi), transfreq)
       absorption = water_atten(np.asarray(depi), transfreq, c, ph, temp, salinity)

       if len(shape_hi)>2:    
          for p in xrange(len(dwnhi_fp)):
             #make an index of every other record
             ind = range(0,np.shape(dwnhi_fp[p])[1])

             Zdepi = depi[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zabsorp = absorption[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zlat = lati[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zlon = loni[shape_hi[2]*p:shape_hi[2]*(p+1)]       
             Zes = ei[shape_hi[2]*p:shape_hi[2]*(p+1)]
             Zns = ni[shape_hi[2]*p:shape_hi[2]*(p+1)]       
                
             try: #parallel processing with all available cores
               w = Parallel(n_jobs=-1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[p][:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)
             except: #fall back to serial
               w = Parallel(n_jobs=1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[p][:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)

             rough, hard, sv_e1, sv_e2, e1a, e1b, e2a, e2b = zip(*w) 

             rough = np.array(rough,'float')
             rough[rough==0.0] = np.nan

             hard = np.array(hard,'float')
             hard[hard==0.0] = np.nan

             sv_e1 = np.array(sv_e1,'float')
             sv_e1[sv_e1==0.0] = np.nan

             sv_e2 = np.array(sv_e2,'float')
             sv_e2[sv_e2==0.0] = np.nan

             try:
                nans, y= humutils.nan_helper(rough)
                rough[nans]= np.interp(y(nans), y(~nans), rough[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(hard)
                hard[nans]= np.interp(y(nans), y(~nans), hard[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e1)
                sv_e1[nans]= np.interp(y(nans), y(~nans), sv_e1[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e2)
                sv_e2[nans]= np.interp(y(nans), y(~nans), sv_e2[~nans])
             except:
                pass

             data = np.column_stack([sv_e1, sv_e2])
             k_means = MiniBatchKMeans(numclusters)
             # fit the model
             k_means.fit(data) 
             values = k_means.cluster_centers_.squeeze()
             labels = k_means.labels_
    
             hardav = humutils.runningMeanFast(hard,integ)
             roughav = humutils.runningMeanFast(rough,integ)

             #f = open(sonpath+base+'rough_and_hard'+str(p)+'.csv', 'wt')
             f = open(os.path.normpath(os.path.join(sonpath,base+'rough_and_hard'+str(p)+'.csv')), 'wt')
             writer = csv.writer(f)
             writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth', 'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label') )
             for i in range(0, len(rough)):
                writer.writerow(( float(Zlon[i]),float(Zlat[i]),float(Zes[i]),float(Zns[i]),float(Zdepi[i]),float(rough[i]),float(hard[i]),float(roughav[i]),float(hardav[i]), labels[i].astype(int) ))
             f.close()

             if doplot==1:
                try:

                   fig = plt.figure()
                   plt.imshow(dwnhi_fp[p], cmap='gray')
                   plt.plot(e1a,'r');
                   plt.plot(e1b,'y');
                   plt.plot(e2a,'c');
                   plt.plot(e2b,'m');
                   plt.axis('tight')
                   #plt.show()
                   custom_save(sonpath,'e1e2_scan'+str(p))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   fig = plt.figure()
                   fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   plt.subplot(221)   
                   plt.plot(sv_e1[labels==0],sv_e2[labels==0],'ko');
                   plt.plot(sv_e1[labels==1],sv_e2[labels==1],'ro');
                   plt.plot(sv_e1[labels==2],sv_e2[labels==2],'bo');
                   plt.xlabel('SV1'); plt.ylabel('SV2')
                   plt.xlim(0,1); plt.ylim(0,1)

                   plt.subplot(222)   
                   plt.plot(rough[labels==0],hard[labels==0],'ko');
                   plt.plot(rough[labels==1],hard[labels==1],'ro');
                   plt.plot(rough[labels==2],hard[labels==2],'bo');
                   plt.xlabel('E1'); plt.ylabel('E2')
                   plt.xlim(1,8); plt.ylim(1,8)
                   #plt.show()
                   custom_save(sonpath,'e1e2_kmeans'+str(p))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   fig = plt.figure()
                   s=plt.scatter(Zes[labels==0],Zns[labels==0],marker='o',c='k', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==1],Zns[labels==1],marker='o',c='r', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==2],Zns[labels==2],marker='o',c='b', s=10, linewidth=0, vmin=0, vmax=8);
                   custom_save(sonpath,'rgh_hard_kmeans'+str(p))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   print "drawing and printing map ..."
                   fig = plt.figure(frameon=False)
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1], #epsg=26949,
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)                   

                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E1')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_rgh'+str(p))
                   del fig 

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:
                   fig = plt.figure()
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)
                      
                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E2')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_hard'+str(p))
                   del fig 

                except:
                   print "plot could not be produced"

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Rough'+str(p))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Rough'+str(p)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Rough'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Rough'+str(p)+'.kml')))

                except:
                   print "plot could not be produced"

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Hard'+str(p))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Hard'+str(p)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Hard'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Hard'+str(p)+'.kml')))

                except:
                   print "plot could not be produced"

       else:
          if 2 > 1: # need to tiday all this up later!!
             #make an index of every other record
             ind = range(0,np.shape(dwnhi_fp)[1])

             Zdepi = depi
             Zabsorp = absorption
             Zlat = lati
             Zlon = loni       
             Zes = ei
             Zns = ni      
                
             try: #parallel processing with all available cores
               w = Parallel(n_jobs=-1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)
             except: #fall back to serial
               w = Parallel(n_jobs=1, verbose=0)(delayed(get_rgh_hrd)(dwnhi_fp[:,i],Zdepi[i],Zabsorp[i],c,nf,transfreq,equivbeam,maxW,pi,ft) for i in ind)

             rough, hard, sv_e1, sv_e2, e1a, e1b, e2a, e2b = zip(*w) 

             rough = np.array(rough,'float')
             rough[rough==0.0] = np.nan

             hard = np.array(hard,'float')
             hard[hard==0.0] = np.nan

             sv_e1 = np.array(sv_e1,'float')
             sv_e1[sv_e1==0.0] = np.nan

             sv_e2 = np.array(sv_e2,'float')
             sv_e2[sv_e2==0.0] = np.nan

             try:
                nans, y= humutils.nan_helper(rough)
                rough[nans]= np.interp(y(nans), y(~nans), rough[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(hard)
                hard[nans]= np.interp(y(nans), y(~nans), hard[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e1)
                sv_e1[nans]= np.interp(y(nans), y(~nans), sv_e1[~nans])
             except:
                pass

             try:
                nans, y= humutils.nan_helper(sv_e2)
                sv_e2[nans]= np.interp(y(nans), y(~nans), sv_e2[~nans])
             except:
                pass

             data = np.column_stack([sv_e1, sv_e2])
             k_means = MiniBatchKMeans(numclusters)
             # fit the model
             k_means.fit(data) 
             values = k_means.cluster_centers_.squeeze()
             labels = k_means.labels_
    
             hardav = humutils.runningMeanFast(hard,integ)
             roughav = humutils.runningMeanFast(rough,integ)

             #f = open(sonpath+base+'rough_and_hard'+str(p)+'.csv', 'wt')
             f = open(os.path.normpath(os.path.join(sonpath,base+'rough_and_hard'+str(0)+'.csv')), 'wt')
             writer = csv.writer(f)
             writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth', 'roughness', 'hardness', 'average roughness', 'average hardness','k-mean label') )
             for i in range(0, len(rough)):
                writer.writerow(( float(Zlon[i]),float(Zlat[i]),float(Zes[i]),float(Zns[i]),float(Zdepi[i]),float(rough[i]),float(hard[i]),float(roughav[i]),float(hardav[i]), labels[i].astype(int) ))
             f.close()

             if doplot==1:
                try:

                   fig = plt.figure()
                   plt.imshow(dwnhi_fp, cmap='gray')
                   plt.plot(e1a,'r');
                   plt.plot(e1b,'y');
                   plt.plot(e2a,'c');
                   plt.plot(e2b,'m');
                   plt.axis('tight')
                   #plt.show()
                   custom_save(sonpath,'e1e2_scan'+str(0))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   fig = plt.figure()
                   fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   plt.subplot(221)   
                   plt.plot(sv_e1[labels==0],sv_e2[labels==0],'ko');
                   plt.plot(sv_e1[labels==1],sv_e2[labels==1],'ro');
                   plt.plot(sv_e1[labels==2],sv_e2[labels==2],'bo');
                   plt.xlabel('SV1'); plt.ylabel('SV2')
                   plt.xlim(0,1); plt.ylim(0,1)

                   plt.subplot(222)   
                   plt.plot(rough[labels==0],hard[labels==0],'ko');
                   plt.plot(rough[labels==1],hard[labels==1],'ro');
                   plt.plot(rough[labels==2],hard[labels==2],'bo');
                   plt.xlabel('E1'); plt.ylabel('E2')
                   plt.xlim(1,8); plt.ylim(1,8)
                   #plt.show()
                   custom_save(sonpath,'e1e2_kmeans'+str(0))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   fig = plt.figure()
                   s=plt.scatter(Zes[labels==0],Zns[labels==0],marker='o',c='k', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==1],Zns[labels==1],marker='o',c='r', s=10, linewidth=0, vmin=0, vmax=8);
                   s=plt.scatter(Zes[labels==2],Zns[labels==2],marker='o',c='b', s=10, linewidth=0, vmin=0, vmax=8);
                   custom_save(sonpath,'rgh_hard_kmeans'+str(0))
                   del fig

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:

                   print "drawing and printing map ..."
                   fig = plt.figure(frameon=False)
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1], #epsg=26949,
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)
  
                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E1')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_rgh'+str(0))
                   del fig 

                except:
                   print "plot could not be produced"

             if doplot==1:
                try:
                   fig = plt.figure()
                   #fig.subplots_adjust(wspace = 0.4, hspace=0.4)
                   map = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
                      resolution = 'i', #h #f
                      llcrnrlon=np.min(Zlon)-0.0001, llcrnrlat=np.min(Zlat)-0.0001,
                      urcrnrlon=np.max(Zlon)+0.0001, urcrnrlat=np.max(Zlat)+0.0001)

                   # draw point cloud
                   x,y = map.projtran(Zlon, Zlat)

                   cs = map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth=0, vmin=0, vmax=8)

                   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)

                   cbar = map.colorbar(cs,location='bottom',pad="5%")
                   cbar.set_label('E2')
                   cbar.set_ticks([0,2,4,6,8])

                   custom_save(sonpath,'map_hard'+str(0))
                   del fig 

                except:
                   print "plot could not be produced"

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, rough.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Rough'+str(0))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Rough'+str(0)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Rough'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Rough'+str(0)+'.kml')))

                except:
                   print "plot could not be produced"

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

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

                   ## draw point cloud
                   x,y = map.projtran(Zlon, Zlat)
                   map.scatter(x.flatten(), y.flatten(), 1, hard.flatten(), linewidth = '0', vmin=0, vmax=8)

                   custom_save(sonpath,'Hard'+str(0))
                   del fig 

                   kml = simplekml.Kml()
                   ground = kml.newgroundoverlay(name='GroundOverlay')
                   ground.icon.href = 'Hard'+str(0)+'.png'
                   ground.latlonbox.north = np.min(Zlat)-0.001
                   ground.latlonbox.south = np.max(Zlat)+0.001
                   ground.latlonbox.east =  np.max(Zlon)+0.001
                   ground.latlonbox.west =  np.min(Zlon)-0.001
                   ground.latlonbox.rotation = 0

                   #kml.save(sonpath+'Hard'+str(p)+'.kml')
                   kml.save(os.path.normpath(os.path.join(sonpath,'Hard'+str(0)+'.kml')))

                except:
                   print "plot could not be produced"         

    else:
       print "high-frequency downward echosounder data not available"
示例#11
0
def correct(humfile, sonpath, maxW, doplot, dofilt, correct_withwater, ph, temp, salinity, dconcfile):

    '''
    Remove water column and carry out some rudimentary radiometric corrections, 
    accounting for directivity and attenuation with range

    Syntax
    ----------
    [] = PyHum.correct(humfile, sonpath, maxW, doplot, correct_withwater, ph, temp, salinity, dconcfile)

    Parameters
    ----------
    humfile : str
       path to the .DAT file

    sonpath : str
       path where the *.SON files are

    maxW : int, *optional* [Default=1000]
       maximum transducer power

    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    dofilt : int, *optional* [Default=0]
       1 = apply a phase preserving filter to the scans

    correct_withwater : int, *optional* [Default=0]
       1 = apply radiometric correction but don't remove water column from scans

    ph : float, *optional* [Default=7.0]
       water acidity in pH

    temp : float, *optional* [Default=10.0]
       water temperature in degrees Celsius

    salinity : float, *optional* [Default=0.0]
       salinity of water in parts per thousand

    dconcfile : str, *optional* [Default=None]
       file path of a text file containing sediment concentration data
       this file must contain the following fields separated by spaces:
       size (microns) conc (mg/L) dens (kg/m3)
       with one row per grain size, for example:
       30 1700 2200
       100 15 2650

    Returns
    -------
    sonpath+base+'_data_star_l.dat': memory-mapped file
        contains the starboard scan with water column removed

    sonpath+base+'_data_port_l.dat': memory-mapped file
        contains the portside scan with water column removed

    sonpath+base+'_data_star_la.dat': memory-mapped file
        contains the starboard scan with water column removed and 
        radiometrically corrected

    sonpath+base+'_data_port_la.dat': memory-mapped file
        contains the portside scan with water column removed and
        radiometrically corrected

    sonpath+base+'_data_range.dat': memory-mapped file
        contains the cosine of the range which is used to correct
        for attenuation with range

    sonpath+base+'_data_dwnlow_l.dat': memory-mapped file
        contains the low freq. downward scan with water column removed

    sonpath+base+'_data_dwnhi_l.dat': memory-mapped file
        contains the high freq. downward  scan with water column removed

    sonpath+base+'_data_dwnlow_la.dat': memory-mapped file
        contains the low freq. downward  scan with water column removed and 
        radiometrically corrected

    sonpath+base+'_data_dwnhi_la.dat': memory-mapped file
        contains the high freq. downward  scan with water column removed and
        radiometrically corrected
    
    if correct_withwater == 1:
    
       sonpath+base+'_data_star_lw.dat': memory-mapped file
           contains the starboard scan with water column retained and 
           radiometrically corrected

       sonpath+base+'_data_port_lw.dat': memory-mapped file
           contains the portside scan with water column retained and
           radiometrically corrected

    '''

    # 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
      inputfile = 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 maxW:
      maxW = np.asarray(maxW,float)
      print('Max. transducer power is %s W' % (str(maxW)))

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

    if dofilt:
      dofilt = int(dofilt)
      if dofilt==0:
         print("Phase preserving filter will not be applied")
      else:
         print("Phase preserving filter will be applied")

    if correct_withwater:
      correct_withwater = int(correct_withwater)
      if correct_withwater==1:
         print("Correction will be applied without removing water column")

    if salinity:
       salinity = np.asarray(salinity,float)
       print('Salinity is %s ppt' % (str(salinity)))

    if ph:
       ph = np.asarray(ph,float)
       print('pH is %s' % (str(ph)))

    if temp:
       temp = np.asarray(temp,float)
       print('Temperature is %s' % (str(temp)))

    if dconcfile is not None:
       try:
          print('Suspended sediment size/conc. file is %s' % (dconcfile))
          dconc = np.genfromtxt(dconcfile).T
          conc = dconc[1]
          dens = dconc[2]
          d = dconc[0]
       except:
          pass

    #================================
    # 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)   

    # add wattage to metadata dict 
    meta = loadmat(os.path.normpath(os.path.join(sonpath,base+'meta.mat')))

    dep_m = meta['dep_m'][0]
    pix_m = meta['pix_m'][0]

    meta['maxW'] = maxW
    savemat(os.path.normpath(os.path.join(sonpath,base+'meta.mat')), meta ,oned_as='row')

    bed = np.squeeze(meta['bed'])
    ft = 1/(meta['pix_m'])
    dist_m = np.squeeze(meta['dist_m'])

    try:
       if dconcfile is not None:
          # sediment attenuation
          alpha = sed_atten(meta['f'],conc,dens,d,meta['c'])
       else:
          alpha = 0
    except:
       alpha = 0

    # 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_port2.dat'))):
          port_fp = io.get_mmap_data(sonpath, base, '_data_port2.dat', 'int16', tuple(shape_port))

       else:
          port_fp = io.get_mmap_data(sonpath, base, '_data_port.dat', 'int16', 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_star2.dat'))):
          star_fp = io.get_mmap_data(sonpath, base, '_data_star2.dat', 'int16', tuple(shape_star))       

       else:
          star_fp = io.get_mmap_data(sonpath, base, '_data_star.dat', 'int16', tuple(shape_star))        

    if len(shape_star)==2:
       extent = shape_star[0] 
    else:
       extent = shape_star[1] #np.shape(data_port)[0]

    bed = np.asarray(bed,'int')+int(0.25*ft)

    # calculate in dB
    ######### star
    Zt, R, A = remove_water(star_fp, bed, shape_star, dep_m, pix_m, 1,  maxW)

    Zt = np.squeeze(Zt)
    
    # create memory mapped file for Z)
    shape_star = io.set_mmap_data(sonpath, base, '_data_star_l.dat', 'float32', Zt)    
    del Zt
    
    A = np.squeeze(A)
    # create memory mapped file for A
    shape_A = io.set_mmap_data(sonpath, base, '_data_incidentangle.dat', 'float32', A)         
    del A

    R = np.squeeze(R)
    R[np.isnan(R)] = 0

    try:
       alpha_w = water_atten(R,meta['f'],meta['c'], ph, temp, salinity)
    except:
       alpha_w = 1e-5

    # compute transmission losses
    TL = (40 * np.log10(R) + alpha_w + (2*alpha)*R/1000)/255
    del alpha_w

    # create memory mapped file for R
    shape_R = io.set_mmap_data(sonpath, base, '_data_range.dat', 'float32', R)  
    del R 
    
    TL[np.isnan(TL)] = 0
    TL[TL<0] = 0
    shape_TL = io.set_mmap_data(sonpath, base, '_data_TL.dat', 'float32', TL)     
    del TL      

    A_fp = io.get_mmap_data(sonpath, base, '_data_incidentangle.dat', 'float32', shape_star)
    TL_fp = io.get_mmap_data(sonpath, base, '_data_TL.dat', 'float32', shape_star)

    R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32', shape_star)
        
    if correct_withwater == 1:
       Zt = correct_scans(star_fp, A_fp, TL_fp, dofilt)

       # create memory mapped file for Z)
       shape_star = io.set_mmap_data(sonpath, base, '_data_star_lw.dat', 'float32', Zt)       

    #we are only going to access the portion of memory required
    star_fp = io.get_mmap_data(sonpath, base, '_data_star_l.dat', 'float32', shape_star)     

    ##Zt = correct_scans(star_fp, A_fp, TL_fp, dofilt)
 
    #phi=1.69
    alpha=59 # vertical beam width at 3db
    theta=35 #opening angle theta 
    
    # lambertian correction
    Zt = correct_scans_lambertian(star_fp, A_fp, TL_fp, R_fp, meta['c'], meta['f'], theta, alpha)
    
    Zt = np.squeeze(Zt)

    avg = np.nanmedian(Zt,axis=0)
    ##avg = median_filter(avg,int(len(avg)/10))
    
    Zt2 = Zt-avg + np.nanmean(avg)
    Zt2 = Zt2 + np.abs(np.nanmin(Zt2))

    try:
       Zt2 = median_filter(Zt2, (3,3))
    except:
       pass

    ##Zt2 = np.empty(np.shape(Zt)) 
    ##for kk in range(np.shape(Zt)[1]):
    ##   Zt2[:,kk] = (Zt[:,kk] - avg) + np.nanmean(avg)
    ##Zt2[Zt<=0] = np.nan
    ##Zt2[Zt2<=0] = np.nan    
    del Zt
    
    # create memory mapped file for Z
    shape_star = io.set_mmap_data(sonpath, base, '_data_star_la.dat', 'float32', Zt2)
    del Zt2    
    
    #we are only going to access the portion of memory required
    star_fp = io.get_mmap_data(sonpath, base, '_data_star_la.dat', 'float32', shape_star) 

    ######### port
    if correct_withwater == 1:
       Zt = correct_scans(port_fp, A_fp, TL, dofilt)

       # create memory mapped file for Z)
       shape_port = io.set_mmap_data(sonpath, base, '_data_port_lw.dat', 'float32', Zt)        

    Zt = remove_water(port_fp, bed, shape_port, dep_m, pix_m, 0,  maxW)

    Zt = np.squeeze(Zt)
    
    # create memory mapped file for Z
    shape_port = io.set_mmap_data(sonpath, base, '_data_port_l.dat', 'float32', Zt)       

    #we are only going to access the portion of memory required
    port_fp = io.get_mmap_data(sonpath, base, '_data_port_l.dat', 'float32', shape_port)     
    
    ##Zt = correct_scans(port_fp, A_fp, TL_fp, dofilt)
    
    # lambertian correction
    Zt = correct_scans_lambertian(port_fp, A_fp, TL_fp, R_fp, meta['c'], meta['f'], theta, alpha)
    
    Zt = np.squeeze(Zt)
    
    Zt2 = Zt-avg + np.nanmean(avg)
    Zt2 = Zt2 + np.abs(np.nanmin(Zt2))

    ##Zt2 = np.empty(np.shape(Zt))
    ##for kk in range(np.shape(Zt)[1]):
    ##   Zt2[:,kk] = (Zt[:,kk] - avg) + np.nanmean(avg)
    ##Zt2[Zt<=0] = np.nan
    ##Zt2[Zt2<=0] = np.nan    
    del Zt
        
    # create memory mapped file for Z
    shape_port = io.set_mmap_data(sonpath, base, '_data_port_la.dat', 'float32', Zt2)       
    del Zt2

    #we are only going to access the portion of memory required
    port_fp = io.get_mmap_data(sonpath, base, '_data_port_la.dat', 'float32', shape_port) 

    ## do plots of merged scans
    if doplot==1:
       if correct_withwater == 1:

          port_fpw = io.get_mmap_data(sonpath, base, '_data_port_lw.dat', 'float32', shape_port) 

          star_fpw = io.get_mmap_data(sonpath, base, '_data_star_lw.dat', 'float32', shape_star) 
          
          if len(np.shape(star_fpw))>2:
             for p in range(len(star_fpw)):
                plot_merged_scans(port_fpw[p], star_fpw[p], dist_m, shape_port, ft, sonpath, p)
          else:
             plot_merged_scans(port_fpw, star_fpw, dist_m, shape_port, ft, sonpath, 0)

       else:

          if len(np.shape(star_fp))>2:
             for p in range(len(star_fp)):
                plot_merged_scans(port_fp[p], star_fp[p], dist_m, shape_port, ft, sonpath, p)
          else:
             plot_merged_scans(port_fp, star_fp, dist_m, shape_port, ft, sonpath, 0)


    # load memory mapped scans
    shape_low = np.squeeze(meta['shape_low'])
    shape_hi = np.squeeze(meta['shape_hi'])
    
    if shape_low!='':
       if os.path.isfile(os.path.normpath(os.path.join(sonpath,base+'_data_dwnlow2.dat'))):
          try:
             low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', tuple(shape_low))           

          except:
             low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', tuple(shape_low)) 

          finally:
             low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', tuple(shape_hi))              

             #if 'shape_hi' in locals():
             #   low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', tuple(shape_hi))              

       else:

          try:
             low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', tuple(shape_low))           

          except:
             if 'shape_hi' in locals():
                low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', tuple(shape_hi))              

    shape_hi = np.squeeze(meta['shape_hi'])

    if shape_hi!='':
       if os.path.isfile(os.path.normpath(os.path.join(sonpath,base+'_data_dwnhi2.dat'))):
          try:
             hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', tuple(shape_hi))           

          except:
             hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', tuple(shape_hi)) 

          finally:
             hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', tuple(shape_low))              


             #if 'shape_low' in locals():
             #   hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', tuple(shape_low))               

       else:
          try:
             hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', tuple(shape_hi))            

          except:
             if 'shape_low' in locals():
                hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', tuple(shape_low))               


    if 'low_fp' in locals():
       ######### low
       Zt = remove_water(low_fp, bed, shape_low, dep_m, pix_m, 0,  maxW)
       Zt = np.squeeze(Zt)

       # create memory mapped file for Z
       shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow_l.dat', 'float32', Zt)       
       del Zt   

       #we are only going to access the portion of memory required
       low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow_l.dat', 'float32', shape_low)         
       Zt = correct_scans2(low_fp, TL_fp)

       # create memory mapped file for Z
       shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow_la.dat', 'float32', Zt)    
       del Zt    

       #we are only going to access the lowion of memory required
       low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow_la.dat', 'float32', shape_low)        
       
       if doplot==1:
          if len(np.shape(low_fp))>2:
             for p in range(len(low_fp)):
                plot_dwnlow_scans(low_fp[p], dist_m, shape_low, ft, sonpath, p)
          else:
             plot_dwnlow_scans(low_fp, dist_m, shape_low, ft, sonpath, 0)

    if 'hi_fp' in locals():
       ######### hi
       Zt = remove_water(hi_fp, bed, shape_hi, dep_m, pix_m, 0,  maxW)
       Zt = np.squeeze(Zt)

       # create memory mapped file for Z
       shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi_l.dat', 'float32', Zt) 
       del Zt       

       #we are only going to access the portion of memory required
       hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi_l.dat', 'float32', shape_hi)        

       Zt = correct_scans2(hi_fp, TL_fp)

       # create memory mapped file for Z
       shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi_la.dat', 'float32', Zt)     
       del Zt  

       #we are only going to access the hiion of memory required
       hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi_la.dat', 'float32', shape_hi)        
       
       if doplot==1:
          if len(np.shape(hi_fp))>2:
             for p in range(len(hi_fp)):
                plot_dwnhi_scans(hi_fp[p], dist_m, shape_hi, ft, sonpath, p)
          else:
             plot_dwnhi_scans(hi_fp, dist_m, shape_hi, ft, sonpath, 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("===================================================")
示例#12
0
def texture(humfile, sonpath, win, shift, doplot, density, numclasses, maxscale, notes):
          
      '''
      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 range(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(np.deg2rad(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(np.deg2rad(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 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, 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("===================================================")    
示例#13
0
def texture_slic(humfile,
                 sonpath,
                 doplot=1,
                 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, doplot, numclasses, maxscale, notes)

      Parameters
      ----------
      humfile : str
       path to the .DAT file
      sonpath : str
       path where the *.SON files are
      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
      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 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]

    #work on the entire scan
    #im = humutils.rescale(np.vstack((np.flipud(np.hstack(port_fp)), np.hstack(star_fp))),0,1)
    im = np.vstack((np.flipud(np.hstack(port_fp)), np.hstack(star_fp)))
    im[np.isnan(im)] = 0
    im = humutils.rescale(im, 0, 1)

    #get SLIC superpixels
    segments_slic = slic(im, n_segments=int(im.shape[0] / 10), compactness=.1)

    #pre-allocate texture lengthscale array
    tl = np.zeros(im.shape, dtype="float64")

    #cycle through each segment and compute tl
    for k in np.unique(segments_slic):
        mask = np.zeros(im.shape[:2], dtype="uint8")
        mask[segments_slic == k] = 255
        cmask, cim = crop_toseg(mask, im)
        tl[segments_slic == k] = parallel_me(cim, maxscale, notes,
                                             np.shape(cim)[0])

    R_fp = io.get_mmap_data(sonpath, base, '_data_range.dat', 'float32',
                            tuple(shape_star))
    R = np.vstack((np.flipud(np.hstack(R_fp)), np.hstack(R_fp)))
    R = R / np.max(R)

    #correct for range and scale
    tl = tl * np.cos(R) * (1 / ft)
    tl[im == 0] = np.nan
    tl[np.isnan(im)] = np.nan

    # 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))

    counter = 0
    if len(shape_star) > 2:
        for p in range(len(port_fp)):
            if p == 0:
                n, m = np.shape(np.vstack((np.flipud(port_fp[p]), star_fp[p])))
            else:
                n, m = np.shape(np.vstack((np.flipud(port_fp[p]), star_fp[p])))
            Sp = tl[:n, counter:counter + m]
            counter = counter + m
            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:

        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)

    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, 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!")
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!")
示例#15
0
def map_texture(humfile, sonpath, cs2cs_args, res, mode, nn, numstdevs): #influence = 10, 
         
    '''
    Create plots of the texture lengthscale maps made in PyHum.texture module 
    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.map_texture(humfile, sonpath, cs2cs_args, res, mode, nn, numstdevs)

    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.5]
       grid resolution of output gridded texture map
    mode: int, *optional* [Default=3]
       gridding mode. 1 = nearest neighbour
                      2 = inverse weighted nearest neighbour
                      3 = Gaussian weighted nearest neighbour
    nn: int, *optional* [Default=64]
       number of nearest neighbours for gridding (used if mode > 1) 
    numstdevs: int, *optional* [Default = 4]
       Threshold number of standard deviations in texture lengthscale per grid cell up to which to accept 
           
    Returns
    -------
    sonpath+'x_y_class'+str(p)+'.asc' : text file
        contains the point cloud of easting, northing, and texture lengthscales
        of the pth chunk

    sonpath+'class_GroundOverlay'+str(p)+'.kml': kml file
        contains gridded (or point cloud) texture lengthscale map for importing into google earth
        of the pth chunk

    sonpath+'class_map'+str(p)+'.png' : 
        image overlay associated with the kml file

    sonpath+'class_map_imagery'+str(p)+'.png' : png image file
        gridded (or point cloud) texture lengthscale map
        overlain onto an image pulled from esri image server

    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 cs2cs_args:
       print('cs2cs arguments are %s' % (cs2cs_args))

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

    if mode:
       mode = int(mode)
       print('Mode for gridding: %s' % (str(mode)))      

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

    #if influence:
    #   influence = int(influence)
    #   print 'Radius of influence for gridding: %s (m)' % (str(influence))             

    if numstdevs:
       numstdevs = int(numstdevs)
       print('Threshold number of standard deviations in texture lengthscale per grid cell up to which to accept: %s' % (str(numstdevs)))         

    # 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']) 

    pix_m = np.squeeze(meta['pix_m'])*1.1
    dep_m = np.squeeze(meta['dep_m'])
    c = np.squeeze(meta['c'])
    #dist_m = np.squeeze(meta['dist_m'])

    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))

    if len(shape_star)>2:    
       shape = shape_port.copy()
       shape[1] = shape_port[1] + shape_star[1]
       class_fp = io.get_mmap_data(sonpath, base, '_data_class.dat', 'float32', tuple(shape))
       #with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'r') as ff:
       #   class_fp = np.memmap(ff, dtype='float32', mode='r', shape=tuple(shape))
    else:
       with open(os.path.normpath(os.path.join(sonpath,base+'_data_class.dat')), 'r') as ff:
          class_fp = np.load(ff)    


    tvg = ((8.5*10**-5)+(3/76923)+((8.5*10**-5)/4))*c
    dist_tvg = ((np.tan(np.radians(25)))*dep_m)-(tvg)

    if len(shape_star)>2:    
       for p in range(len(class_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)]

          len_n = len(n)
   
          merge = class_fp[p].copy()

          merge[np.isnan(merge)] = 0
          merge[np.isnan(np.vstack((np.flipud(port_fp[p]),star_fp[p])))] = 0

          extent = shape_port[1]
          R1 = merge[extent:,:]
          R2 = np.flipud(merge[:extent,:])

          merge = np.vstack((R2,R1))
          del R1, R2

          # get number pixels in scan line
          extent = int(np.shape(merge)[0]/2)

          yvec = np.linspace(pix_m,extent*pix_m,extent)

          X, Y  = getXY(e,n,yvec,d,t,extent)

          merge[merge==0] = np.nan

          if len(merge.flatten()) != len(X):
             merge = merge[:,:len_n]

          merge = merge.T.flatten()

          index = np.where(np.logical_not(np.isnan(merge)))[0]

          X, Y, merge = trim_xys(X, Y, merge, index)

          X = X.astype('float32')
          Y = Y.astype('float32')
          merge = merge.astype('float32')
          
          # write raw bs to file
          outfile = os.path.normpath(os.path.join(sonpath,'x_y_class'+str(p)+'.asc'))
          with open(outfile, 'w') as f:
             np.savetxt(f, np.hstack((humutils.ascol(X),humutils.ascol(Y), humutils.ascol(merge))), delimiter=' ', fmt="%8.6f %8.6f %8.6f")

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

          #if dogrid==1:

          orig_def, targ_def, grid_x, grid_y, res, shape = get_griddefs(np.min(X), np.max(X), np.min(Y), np.max(Y), res, humlon, humlat, trans)

          grid_x = grid_x.astype('float32')
          grid_y = grid_y.astype('float32')
                                      
          sigmas = 1 #m
          eps = 2
          dat, res = get_grid(mode, orig_def, targ_def, merge, res*10, np.min(X), np.max(X), np.min(Y), np.max(Y), res, nn, sigmas, eps, shape, numstdevs, trans, humlon, humlat)
          
          del merge
             
          dat[dat==0] = np.nan
          dat[np.isinf(dat)] = np.nan

          datm = np.ma.masked_invalid(dat)
          del dat

          glon, glat = trans(grid_x, grid_y, inverse=True)
          del grid_x, grid_y
          
          vmin=np.nanmin(datm)+0.1
          vmax=np.nanmax(datm)-0.1
          if vmin > vmax:
             vmin=np.nanmin(datm)
             vmax=np.nanmax(datm)            
          
          print_map(cs2cs_args, glon, glat, datm, sonpath, p, vmin=vmin, vmax=vmax)

    else: #just 1 chunk   
    
       e = esi
       n = nsi
       t = theta
       d = dist_tvg

       len_n = len(n)
   
       merge = class_fp.copy()

       merge[np.isnan(merge)] = 0
       merge[np.isnan(np.vstack((np.flipud(port_fp),star_fp)))] = 0

       extent = shape_port[0]
       R1 = merge[extent:,:]
       R2 = np.flipud(merge[:extent,:])

       merge = np.vstack((R2,R1))
       del R1, R2

       # get number pixels in scan line
       extent = int(np.shape(merge)[0]/2)

       yvec = np.linspace(pix_m,extent*pix_m,extent)

       X, Y  = getXY(e,n,yvec,d,t,extent)

       merge[merge==0] = np.nan

       if len(merge.flatten()) != len(X):
          merge = merge[:,:len_n]

       merge = merge.T.flatten()

       index = np.where(np.logical_not(np.isnan(merge)))[0]

       X, Y, merge = trim_xys(X, Y, merge, index)

       # write raw bs to file
       outfile = os.path.normpath(os.path.join(sonpath,'x_y_class'+str(0)+'.asc'))
       with open(outfile, 'w') as f:
          np.savetxt(f, np.hstack((humutils.ascol(X),humutils.ascol(Y), humutils.ascol(merge))), delimiter=' ', fmt="%8.6f %8.6f %8.6f")

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

       #if dogrid==1:
       if 2>1:

          orig_def, targ_def, grid_x, grid_y, res, shape = get_griddefs(np.min(X), np.max(X), np.min(Y), np.max(Y), res, humlon, humlat, trans)

          ## create mask for where the data is not
          tree = KDTree(np.c_[X.flatten(),Y.flatten()])

          if pykdtree==1:
             dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1)                      
          else:
             try:
                dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1, n_jobs=cpu_count())
             except:
                #print ".... update your scipy installation to use faster kd-tree queries"
                dist, _ = tree.query(np.c_[grid_x.ravel(), grid_y.ravel()], k=1)

          dist = dist.reshape(grid_x.shape)
             
          sigmas = 1 #m
          eps = 2
          dat, res = get_grid(mode, orig_def, targ_def, merge, res*10, np.min(X), np.max(X), np.min(Y), np.max(Y), res, nn, sigmas, eps, shape, numstdevs, trans, humlon, humlat)
          
          del merge

       #if dogrid==1:
       if 2>1:
          dat[dat==0] = np.nan
          dat[np.isinf(dat)] = np.nan
          dat[dist>res*2] = np.nan
          del dist

          datm = np.ma.masked_invalid(dat)

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

       vmin=np.nanmin(datm)+0.1
       vmax=np.nanmax(datm)-0.1
       if vmin > vmax:
         vmin=np.nanmin(datm)
         vmax=np.nanmax(datm)
       
       Parallel(n_jobs = 2, verbose=0)(delayed(doplots)(k, humlon, humlat, cs2cs_args, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax) for k in range(2)) 
       
       #print_map(cs2cs_args, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax)

       #print_contour_map(cs2cs_args, humlon, humlat, glon, glat, datm, sonpath, 0, vmin=vmin, vmax=vmax) 

    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("===================================================")
示例#16
0
def map(humfile, sonpath, cs2cs_args, res, mode, nn, numstdevs, use_uncorrected, scalemax): #dogrid = 1, influence = 1, dowrite = 0, 

    '''
    Create plots of the spatially referenced sidescan echograms

    Syntax
    ----------
    [] = PyHum.map(humfile, sonpath, cs2cs_args, res, mode, nn, numstdevs)

    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=0, res will be determined automatically from the spatial resolution of 1 pixel
    mode: int, *optional* [Default=3]
       gridding mode. 1 = nearest neighbour
                      2 = inverse weighted nearest neighbour
                      3 = Gaussian weighted nearest neighbour
    nn: int, *optional* [Default=64]
       number of nearest neighbours for gridding (used if mode > 1)
    numstdevs: int, *optional* [Default = 4]
       Threshold number of standard deviations in sidescan intensity per grid cell up to which to accept


    Returns
    -------
    sonpath+'x_y_ss_raw'+str(p)+'.asc'  : text file
        contains the point cloud of easting, northing, and sidescan intensity
        of the pth chunk

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

    sonpath+'map'+str(p)+'.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 mode:
       mode = int(mode)
       print('Mode for gridding: %s' % (str(mode)))

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

    if numstdevs:
       numstdevs = int(numstdevs)
       print('Threshold number of standard deviations in sidescan intensity per grid cell up to which to accept: %s' % (str(numstdevs)))

    if use_uncorrected:
       use_uncorrected = int(use_uncorrected)
       if use_uncorrected==1:
          print("Radiometrically uncorrected scans will be used")


    # 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'])
    shape_star = np.squeeze(meta['shape_star'])

    if use_uncorrected == 1:
       print("using uncorrected scans")
       if shape_port!='':
          port_fp = io.get_mmap_data(sonpath, base, '_data_port_l.dat', 'float32', tuple(shape_port))
       if shape_port!='':
          star_fp = io.get_mmap_data(sonpath, base, '_data_star_l.dat', 'float32', tuple(shape_star))

    else:
       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))

       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))

    # for debugging/testing
#    p=0
#    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]
#    dx=np.arcsin(meta['c']/(1000*meta['t']*meta['f']))

#    e = esi;# del esi
#    n = nsi; #del nsi
#    t = theta;# del theta
#    d = dist_tvg;# del dist_tvg
#    dat_port = port_fp;# del port_fp
#    dat_star = star_fp; #del star_fp
#    data_R = R_fp; #del R_fp

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

    if res==0:
       res=99

    print("Number of chunks for mapping: %s" % (len(star_fp)))

    if len(shape_star)>2:
       for p in range(len(star_fp)):
          try:
             print("progress: " + str(p) + " / " + str(len(star_fp)))
             res = make_map(esi[shape_port[-1]*p:shape_port[-1]*(p+1)], nsi[shape_port[-1]*p:shape_port[-1]*(p+1)], theta[shape_port[-1]*p:shape_port[-1]*(p+1)], dist_tvg[shape_port[-1]*p:shape_port[-1]*(p+1)], port_fp[p], star_fp[p], R_fp[p], meta['pix_m'], res, cs2cs_args, sonpath, p, mode, nn, numstdevs, meta['c'], np.arcsin(meta['c']/(1000*meta['t']*meta['f'])), use_uncorrected, scalemax) #dogrid, influence, dowrite,
             print("grid resolution is %s" % (str(res)))
          except:
             print("error on chunk "+str(p))             
    else:
       res = make_map(esi, nsi, theta, dist_tvg, port_fp, star_fp, R_fp, meta['pix_m'], res, cs2cs_args, sonpath, 0, mode, nn, numstdevs, meta['c'], np.arcsin(meta['c']/(1000*meta['t']*meta['f'])), use_uncorrected, scalemax) #dogrid, influence,dowrite,

    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("===================================================")
示例#17
0
def correct(humfile,
            sonpath,
            maxW=1000,
            doplot=1,
            dofilt=0,
            correct_withwater=0,
            ph=7,
            temp=10,
            salinity=0,
            dconcfile=None):
    '''
    Remove water column and carry out some rudimentary radiometric corrections, 
    accounting for directivity and attenuation with range

    Syntax
    ----------
    [] = PyHum.correct(humfile, sonpath, maxW, doplot, correct_withwater, ph, temp, salinity, dconcfile)

    Parameters
    ----------
    humfile : str
       path to the .DAT file

    sonpath : str
       path where the *.SON files are

    maxW : int, *optional* [Default=1000]
       maximum transducer power

    doplot : int, *optional* [Default=1]
       1 = make plots, otherwise do not

    dofilt : int, *optional* [Default=0]
       1 = apply a phase preserving filter to the scans

    correct_withwater : int, *optional* [Default=0]
       1 = apply radiometric correction but don't remove water column from scans

    ph : float, *optional* [Default=7.0]
       water acidity in pH

    temp : float, *optional* [Default=10.0]
       water temperature in degrees Celsius

    salinity : float, *optional* [Default=0.0]
       salinity of water in parts per thousand

    dconcfile : str, *optional* [Default=None]
       file path of a text file containing sediment concentration data
       this file must contain the following fields separated by spaces:
       size (microns) conc (mg/L) dens (kg/m3)
       with one row per grain size, for example:
       30 1700 2200
       100 15 2650

    Returns
    -------
    sonpath+base+'_data_star_l.dat': memory-mapped file
        contains the starboard scan with water column removed

    sonpath+base+'_data_port_l.dat': memory-mapped file
        contains the portside scan with water column removed

    sonpath+base+'_data_star_la.dat': memory-mapped file
        contains the starboard scan with water column removed and 
        radiometrically corrected

    sonpath+base+'_data_port_la.dat': memory-mapped file
        contains the portside scan with water column removed and
        radiometrically corrected

    sonpath+base+'_data_range.dat': memory-mapped file
        contains the cosine of the range which is used to correct
        for attenuation with range

    sonpath+base+'_data_dwnlow_l.dat': memory-mapped file
        contains the low freq. downward scan with water column removed

    sonpath+base+'_data_dwnhi_l.dat': memory-mapped file
        contains the high freq. downward  scan with water column removed

    sonpath+base+'_data_dwnlow_la.dat': memory-mapped file
        contains the low freq. downward  scan with water column removed and 
        radiometrically corrected

    sonpath+base+'_data_dwnhi_la.dat': memory-mapped file
        contains the high freq. downward  scan with water column removed and
        radiometrically corrected
    
    if correct_withwater == 1:
    
       sonpath+base+'_data_star_lw.dat': memory-mapped file
           contains the starboard scan with water column retained and 
           radiometrically corrected

       sonpath+base+'_data_port_lw.dat': memory-mapped file
           contains the portside scan with water column retained and
           radiometrically corrected

    '''

    # 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
        inputfile = 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 maxW:
        maxW = np.asarray(maxW, float)
        print 'Max. transducer power is %s W' % (str(maxW))

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

    if dofilt:
        dofilt = int(dofilt)
        if dofilt == 0:
            print "Phase preserving filter will not be applied"
        else:
            print "Phase preserving filter will be applied"

    if correct_withwater:
        correct_withwater = int(correct_withwater)
        if correct_withwater == 1:
            print "Correction will be applied without removing water column"

    if salinity:
        salinity = np.asarray(salinity, float)
        print 'Salinity is %s ppt' % (str(salinity))

    if ph:
        ph = np.asarray(ph, float)
        print 'pH is %s' % (str(ph))

    if temp:
        temp = np.asarray(temp, float)
        print 'Temperature is %s' % (str(temp))

    if dconcfile is not None:
        try:
            print 'Suspended sediment size/conc. file is %s' % (dconcfile)
            dconc = np.genfromtxt(dconcfile).T
            conc = dconc[1]
            dens = dconc[2]
            d = dconc[0]
        except:
            pass

    #================================
    # 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)

    # add wattage to metadata dict
    meta = loadmat(os.path.normpath(os.path.join(sonpath, base + 'meta.mat')))

    dep_m = meta['dep_m'][0]
    pix_m = meta['pix_m'][0]

    meta['maxW'] = maxW
    savemat(os.path.normpath(os.path.join(sonpath, base + 'meta.mat')),
            meta,
            oned_as='row')

    bed = np.squeeze(meta['bed'])
    ft = 1 / (meta['pix_m'])
    dist_m = np.squeeze(meta['dist_m'])

    try:
        if dconcfile is not None:
            # sediment attenuation
            alpha = sed_atten(meta['f'], conc, dens, d, meta['c'])
        else:
            alpha = 0
    except:
        alpha = 0

    # 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_port2.dat'))):
            port_fp = io.get_mmap_data(sonpath, base, '_data_port2.dat',
                                       'int16', tuple(shape_port))

        else:
            port_fp = io.get_mmap_data(sonpath, base, '_data_port.dat',
                                       'int16', 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_star2.dat'))):
            star_fp = io.get_mmap_data(sonpath, base, '_data_star2.dat',
                                       'int16', tuple(shape_star))

        else:
            star_fp = io.get_mmap_data(sonpath, base, '_data_star.dat',
                                       'int16', tuple(shape_star))

    if len(shape_star) == 2:
        extent = shape_star[0]
    else:
        extent = shape_star[1]  #np.shape(data_port)[0]

    bed = np.asarray(bed, 'int') + int(0.25 * ft)

    # calculate in dB
    ######### star
    Zt, R, A = remove_water(star_fp, bed, shape_star, dep_m, pix_m, 1, maxW)

    Zt = np.squeeze(Zt)

    # create memory mapped file for Z)
    shape_star = io.set_mmap_data(sonpath, base, '_data_star_l.dat', 'float32',
                                  Zt)
    del Zt

    A = np.squeeze(A)
    # create memory mapped file for A
    shape_A = io.set_mmap_data(sonpath, base, '_data_incidentangle.dat',
                               'float32', A)
    del A

    R = np.squeeze(R)
    R[np.isnan(R)] = 0

    try:
        alpha_w = water_atten(R, meta['f'], meta['c'], ph, temp, salinity)
    except:
        alpha_w = 1e-5

    # compute transmission losses
    TL = (40 * np.log10(R) + alpha_w + (2 * alpha) * R / 1000) / 255
    del alpha_w

    # create memory mapped file for R
    shape_R = io.set_mmap_data(sonpath, base, '_data_range.dat', 'float32', R)
    del R

    TL[np.isnan(TL)] = 0
    TL[TL < 0] = 0
    shape_TL = io.set_mmap_data(sonpath, base, '_data_TL.dat', 'float32', TL)
    del TL

    A_fp = io.get_mmap_data(sonpath, base, '_data_incidentangle.dat',
                            'float32', shape_star)
    TL_fp = io.get_mmap_data(sonpath, base, '_data_TL.dat', 'float32',
                             shape_star)

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

    if correct_withwater == 1:
        Zt = correct_scans(star_fp, A_fp, TL_fp, dofilt)

        # create memory mapped file for Z)
        shape_star = io.set_mmap_data(sonpath, base, '_data_star_lw.dat',
                                      'float32', Zt)

    #we are only going to access the portion of memory required
    star_fp = io.get_mmap_data(sonpath, base, '_data_star_l.dat', 'float32',
                               shape_star)

    ##Zt = correct_scans(star_fp, A_fp, TL_fp, dofilt)

    #phi=1.69
    alpha = 59  # vertical beam width at 3db
    theta = 35  #opening angle theta

    # lambertian correction
    Zt = correct_scans_lambertian(star_fp, A_fp, TL_fp, R_fp, meta['c'],
                                  meta['f'], theta, alpha)

    Zt = np.squeeze(Zt)

    avg = np.nanmedian(Zt, axis=1)

    Zt2 = np.empty(np.shape(Zt))

    for kk in xrange(np.shape(Zt)[1]):
        Zt2[:, kk] = (Zt[:, kk] - avg) + np.nanmean(avg)
    Zt2[Zt <= 0] = np.nan
    Zt2[Zt2 <= 0] = np.nan
    del Zt

    # create memory mapped file for Z
    shape_star = io.set_mmap_data(sonpath, base, '_data_star_la.dat',
                                  'float32', Zt2)
    del Zt2

    #we are only going to access the portion of memory required
    star_fp = io.get_mmap_data(sonpath, base, '_data_star_la.dat', 'float32',
                               shape_star)

    ######### port
    if correct_withwater == 1:
        Zt = correct_scans(port_fp, A_fp, TL, dofilt)

        # create memory mapped file for Z)
        shape_port = io.set_mmap_data(sonpath, base, '_data_port_lw.dat',
                                      'float32', Zt)

    Zt = remove_water(port_fp, bed, shape_port, dep_m, pix_m, 0, maxW)

    Zt = np.squeeze(Zt)

    # create memory mapped file for Z
    shape_port = io.set_mmap_data(sonpath, base, '_data_port_l.dat', 'float32',
                                  Zt)

    #we are only going to access the portion of memory required
    port_fp = io.get_mmap_data(sonpath, base, '_data_port_l.dat', 'float32',
                               shape_port)

    ##Zt = correct_scans(port_fp, A_fp, TL_fp, dofilt)

    # lambertian correction
    Zt = correct_scans_lambertian(port_fp, A_fp, TL_fp, R_fp, meta['c'],
                                  meta['f'], theta, alpha)

    Zt = np.squeeze(Zt)

    Zt2 = np.empty(np.shape(Zt))

    for kk in xrange(np.shape(Zt)[1]):
        Zt2[:, kk] = (Zt[:, kk] - avg) + np.nanmean(avg)
    Zt2[Zt <= 0] = np.nan
    Zt2[Zt2 <= 0] = np.nan
    del Zt

    # create memory mapped file for Z
    shape_port = io.set_mmap_data(sonpath, base, '_data_port_la.dat',
                                  'float32', Zt2)
    del Zt2

    #we are only going to access the portion of memory required
    port_fp = io.get_mmap_data(sonpath, base, '_data_port_la.dat', 'float32',
                               shape_port)

    ## do plots of merged scans
    if doplot == 1:
        if correct_withwater == 1:

            port_fpw = io.get_mmap_data(sonpath, base, '_data_port_lw.dat',
                                        'float32', shape_port)

            star_fpw = io.get_mmap_data(sonpath, base, '_data_star_lw.dat',
                                        'float32', shape_star)

            if len(np.shape(star_fpw)) > 2:
                for p in xrange(len(star_fpw)):
                    plot_merged_scans(port_fpw[p], star_fpw[p], dist_m,
                                      shape_port, ft, sonpath, p)
            else:
                plot_merged_scans(port_fpw, star_fpw, dist_m, shape_port, ft,
                                  sonpath, 0)

        else:

            if len(np.shape(star_fp)) > 2:
                for p in xrange(len(star_fp)):
                    plot_merged_scans(port_fp[p], star_fp[p], dist_m,
                                      shape_port, ft, sonpath, p)
            else:
                plot_merged_scans(port_fp, star_fp, dist_m, shape_port, ft,
                                  sonpath, 0)

    # load memory mapped scans
    shape_low = np.squeeze(meta['shape_low'])
    shape_hi = np.squeeze(meta['shape_hi'])

    if shape_low != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_dwnlow2.dat'))):
            try:
                low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat',
                                          'int16', tuple(shape_low))

            except:
                low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat',
                                          'int16', tuple(shape_low))

            finally:
                low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat',
                                          'int16', tuple(shape_hi))

                #if 'shape_hi' in locals():
                #   low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', tuple(shape_hi))

        else:

            try:
                low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat',
                                          'int16', tuple(shape_low))

            except:
                if 'shape_hi' in locals():
                    low_fp = io.get_mmap_data(sonpath, base,
                                              '_data_dwnlow.dat', 'int16',
                                              tuple(shape_hi))

    shape_hi = np.squeeze(meta['shape_hi'])

    if shape_hi != '':
        if os.path.isfile(
                os.path.normpath(
                    os.path.join(sonpath, base + '_data_dwnhi2.dat'))):
            try:
                hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat',
                                         'int16', tuple(shape_hi))

            except:
                hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat',
                                         'int16', tuple(shape_hi))

            finally:
                hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat',
                                         'int16', tuple(shape_low))

                #if 'shape_low' in locals():
                #   hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', tuple(shape_low))

        else:
            try:
                hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat',
                                         'int16', tuple(shape_hi))

            except:
                if 'shape_low' in locals():
                    hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat',
                                             'int16', tuple(shape_low))

    if 'low_fp' in locals():
        ######### low
        Zt = remove_water(low_fp, bed, shape_low, dep_m, pix_m, 0, maxW)
        Zt = np.squeeze(Zt)

        # create memory mapped file for Z
        shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow_l.dat',
                                     'float32', Zt)
        del Zt

        #we are only going to access the portion of memory required
        low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow_l.dat',
                                  'float32', shape_low)
        Zt = correct_scans2(low_fp, TL_fp)

        # create memory mapped file for Z
        shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow_la.dat',
                                     'float32', Zt)
        del Zt

        #we are only going to access the lowion of memory required
        low_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow_la.dat',
                                  'float32', shape_low)

        if doplot == 1:
            if len(np.shape(low_fp)) > 2:
                for p in xrange(len(low_fp)):
                    plot_dwnlow_scans(low_fp[p], dist_m, shape_low, ft,
                                      sonpath, p)
            else:
                plot_dwnlow_scans(low_fp, dist_m, shape_low, ft, sonpath, 0)

    if 'hi_fp' in locals():
        ######### hi
        Zt = remove_water(hi_fp, bed, shape_hi, dep_m, pix_m, 0, maxW)
        Zt = np.squeeze(Zt)

        # create memory mapped file for Z
        shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi_l.dat',
                                    'float32', Zt)
        del Zt

        #we are only going to access the portion of memory required
        hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi_l.dat', 'float32',
                                 shape_hi)

        Zt = correct_scans2(hi_fp, TL_fp)

        # create memory mapped file for Z
        shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi_la.dat',
                                    'float32', Zt)
        del Zt

        #we are only going to access the hiion of memory required
        hi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi_la.dat',
                                 'float32', shape_hi)

        if doplot == 1:
            if len(np.shape(hi_fp)) > 2:
                for p in xrange(len(hi_fp)):
                    plot_dwnhi_scans(hi_fp[p], dist_m, shape_hi, ft, sonpath,
                                     p)
            else:
                plot_dwnhi_scans(hi_fp, dist_m, shape_hi, ft, sonpath, 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!"
示例#18
0
# modify paths below

if __name__ == '__main__':

    humfile = r"C:\workspace\Reach_4a\2014_09\R01767\R01767.DAT"
    sonpath = r"C:\workspace\Reach_4a\2014_09\R01767"
    # 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')))

    ### 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:
示例#19
0
def read(humfile, sonpath, cs2cs_args, c, draft, doplot, t, bedpick, flip_lr, model, calc_bearing, filt_bearing, chunk): #cog = 1,

    '''
    Read a .DAT and associated set of .SON files recorded by a Humminbird(R)
    instrument.

    Parse the data into a set of memory mapped files that will
    subsequently be used by the other functions of the PyHum module.

    Export time-series data and metadata in other formats.

    Create a kml file for visualising boat track

    Syntax
    ----------
    [] = PyHum.read(humfile, sonpath, cs2cs_args, c, draft, doplot, t, bedpick, flip_lr, chunksize, model, calc_bearing, filt_bearing, chunk)

    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
    c : float, *optional* [Default=1450.0]
       speed of sound in water (m/s). Defaults to a value of freshwater
    draft : float, *optional* [Default=0.3]
       draft from water surface to transducer face (m)
    doplot : float, *optional* [Default=1]
       if 1, plots will be made
    t : float, *optional* [Default=0.108]
       length of transducer array (m).
       Default value is that of the 998 series Humminbird(R)
    bedpick : int, *optional* [Default=1]
       if 1, bedpicking with be carried out automatically
       if 0, user will be prompted to pick the bed location on screen
    flip_lr : int, *optional* [Default=0]
       if 1, port and starboard scans will be flipped
       (for situations where the transducer is flipped 180 degrees)
    model: int, *optional* [Default=998]
       A 3 or 4 number code indicating the model number
       Examples: 998, 997, 1198, 1199
    calc_bearing : float, *optional* [Default=0]
       if 1, bearing will be calculated from coordinates
    filt_bearing : float, *optional* [Default=0]
       if 1, bearing will be filtered
    chunk : str, *optional* [Default='d100' (distance, 100 m)]
       letter, followed by a number.
       There are the following letter options:
       'd' - parse chunks based on distance, then number which is distance in m
       'p' - parse chunks based on number of pings, then number which is number of pings
       'h' - parse chunks based on change in heading, then number which is the change in heading in degrees
       '1' - process just 1 chunk

    Returns
    ---------
    sonpath+base+'_data_port.dat': memory-mapped file
        contains the raw echogram from the port side
        sidescan sonar (where present)

    sonpath+base+'_data_port.dat': memory-mapped file
        contains the raw echogram from the starboard side
        sidescan sonar (where present)

    sonpath+base+'_data_dwnhi.dat': memory-mapped file
        contains the raw echogram from the high-frequency
        echosounder (where present)

    sonpath+base+'_data_dwnlow.dat': memory-mapped file
        contains the raw echogram from the low-frequency
        echosounder (where present)

    sonpath+base+"trackline.kml": google-earth kml file
        contains the trackline of the vessel during data
        acquisition

    sonpath+base+'rawdat.csv': comma separated value file
        contains time-series data. columns corresponding to
        longitude
        latitude
        easting (m)
        northing (m)
        depth to bed (m)
        alongtrack cumulative distance (m)
        vessel heading (deg.)

    sonpath+base+'meta.mat': .mat file
        matlab format file containing a dictionary object
        holding metadata information. Fields are:
        e : ndarray, easting (m)
        n : ndarray, northing (m)
        es : ndarray, low-pass filtered easting (m)
        ns : ndarray, low-pass filtered northing (m)
        lat : ndarray, latitude
        lon : ndarray, longitude
        shape_port : tuple, shape of port scans in memory mapped file
        shape_star : tuple, shape of starboard scans in memory mapped file
        shape_hi : tuple, shape of high-freq. scans in memory mapped file
        shape_low : tuple, shape of low-freq. scans in memory mapped file
        dep_m : ndarray, depth to bed (m)
        dist_m : ndarray, distance along track (m)
        heading : ndarray, heading of vessel (deg. N)
        pix_m: float, size of 1 pixel in across-track dimension (m)
        bed : ndarray, depth to bed (m)
        c : float, speed of sound in water (m/s)
        t : length of sidescan transducer array (m)
        spd : ndarray, vessel speed (m/s)
        time_s : ndarray, time elapsed (s)
        caltime : ndarray, unix epoch time (s)
    '''

    # 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('Son files are in %s' % (sonpath))

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

    if draft:
      draft = float(draft)
      print('Draft: %s' % (str(draft)))

    if c:
      c = float(c)
      print('Celerity of sound: %s m/s' % (str(c)))

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

    if flip_lr:
      flip_lr = int(flip_lr)
      if flip_lr==1:
         print("Port and starboard will be flipped")

    if t:
      t = np.asarray(t,float)
      print('Transducer length is %s m' % (str(t)))

    if bedpick:
      bedpick = np.asarray(bedpick,int)
      if bedpick==1:
         print('Bed picking is auto')
      elif bedpick==0:
         print('Bed picking is manual')
      else:
         print('User will be prompted per chunk about bed picking method')

    if chunk:
       chunk = str(chunk)
       if chunk[0]=='d':
          chunkmode=1
          chunkval = int(chunk[1:])
          print('Chunks based on distance of %s m' % (str(chunkval)))
       elif chunk[0]=='p':
          chunkmode=2
          chunkval = int(chunk[1:])
          print('Chunks based on %s pings' % (str(chunkval)))
       elif chunk[0]=='h':
          chunkmode=3
          chunkval = int(chunk[1:])
          print('Chunks based on heading devation of %s degrees' % (str(chunkval)))
       elif chunk[0]=='1':
          chunkmode=4
          chunkval = 1
          print('Only 1 chunk will be produced')
       else:
          print("Chunk mode not understood - should be 'd', 'p', or 'h' - using defaults")
          chunkmode=1
          chunkval = 100
          print('Chunks based on distance of %s m' % (str(chunkval)))

    if model:
       try:
          model = int(model)
          print("Data is from the %s series"  % (str(model)))
       except:
          if model=='onix':
             model=0
             print("Data is from the ONIX series")
          elif model=='helix':
             model=1
             print("Data is from the HELIX series")
          elif model=='mega':
             model=2
             print("Data is from the MEGA series")
#    if cog:
#       cog = int(cog)
#       if cog==1:
#          print "Heading based on course-over-ground"

    if calc_bearing:
       calc_bearing = int(calc_bearing)
       if calc_bearing==1:
          print("Bearing will be calculated from coordinates")

    if filt_bearing:
       filt_bearing = int(filt_bearing)
       if filt_bearing==1:
          print("Bearing will be filtered")

    ## for debugging
    #humfile = r"test.DAT"; sonpath = "test_data"
    #cs2cs_args = "epsg:26949"; doplot = 1; draft = 0
    #c=1450; bedpick=1; fliplr=1; chunk = 'd100'
    #model=998; cog=1; calc_bearing=0; filt_bearing=0

    #if model==2:
    #   f = 1000
    #else:
    f = 455

    try:
       print("Checking the epsg code you have chosen for compatibility with Basemap ... ")
       from mpl_toolkits.basemap import Basemap
       m = Basemap(projection='merc', epsg=cs2cs_args.split(':')[1],
          resolution = 'i', llcrnrlon=10, llcrnrlat=10, urcrnrlon=30, urcrnrlat=30)
       del m
       print("... epsg code compatible")
    except (ValueError):
       print("Error: the epsg code you have chosen is not compatible with Basemap")
       print("please choose a different epsg code (http://spatialreference.org/)")
       print("program will now close")
       sys.exit()

    # 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

    # get the SON files from this directory
    sonfiles = glob.glob(sonpath+'*.SON')
    if not sonfiles:
        sonfiles = glob.glob(os.getcwd()+os.sep+sonpath+'*.SON')

    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)

    print("WARNING: Because files have to be read in byte by byte,")
    print("this could take a very long time ...")

    #reading each sonfile in parallel should be faster ...
    try:
       o = Parallel(n_jobs = np.min([len(sonfiles), cpu_count()]), verbose=0)(delayed(getscans)(sonfiles[k], humfile, c, model, cs2cs_args) for k in range(len(sonfiles)))
       X, Y, A, B = zip(*o)

       for k in range(len(Y)):
          if Y[k] == 'sidescan_port':
             dat = A[k] #data.gethumdat()
             metadat = B[k] #data.getmetadata()
             if flip_lr==0:
                data_port = X[k].astype('int16')
             else:
                data_star = X[k].astype('int16')

          elif Y[k] == 'sidescan_starboard':
             if flip_lr==0:
                data_star = X[k].astype('int16')
             else:
                data_port = X[k].astype('int16')

          elif Y[k] == 'down_lowfreq':
             data_dwnlow = X[k].astype('int16')

          elif Y[k] == 'down_highfreq':
             data_dwnhi = X[k].astype('int16')

          elif Y[k] == 'down_vhighfreq': #hopefully this only applies to mega systems
             data_dwnhi = X[k].astype('int16')

       del X, Y, A, B, o
       old_pyread = 0

       if 'data_port' not in locals():
          data_port = ''
          print("portside scan not available")

       if 'data_star' not in locals():
          data_star = ''
          print("starboardside scan not available")

       if 'data_dwnhi' not in locals():
          data_dwnlow = ''
          print("high-frq. downward scan not available")

       if 'data_dwnlow' not in locals():
          data_dwnlow = ''
          print("low-frq. downward scan not available")

    except: # revert back to older version if paralleleised version fails

       print("something went wrong with the parallelised version of pyread ...")

       try:
          import pyread
       except:
          from . import pyread

       data = pyread.pyread(sonfiles, humfile, c, model, cs2cs_args)

       dat = data.gethumdat()

       metadat = data.getmetadata()

       old_pyread = 1

    nrec = len(metadat['n'])

    metadat['instr_heading'] = metadat['heading'][:nrec]

    #metadat['heading'] = humutils.get_bearing(calc_bearing, filt_bearing, cog, metadat['lat'], metadat['lon'], metadat['instr_heading'])

    try:
       es = humutils.runningMeanFast(metadat['e'][:nrec],len(metadat['e'][:nrec])/100)
       ns = humutils.runningMeanFast(metadat['n'][:nrec],len(metadat['n'][:nrec])/100)
    except:
       es = metadat['e'][:nrec]
       ns = metadat['n'][:nrec]

    metadat['es'] = es
    metadat['ns'] = ns

    try:
       trans =  pyproj.Proj(init=cs2cs_args)
    except:
       trans =  pyproj.Proj(cs2cs_args.lstrip(), inverse=True)

    lon, lat = trans(es, ns, inverse=True)
    metadat['lon'] = lon
    metadat['lat'] = lat

    metadat['heading'] = humutils.get_bearing(calc_bearing, filt_bearing, metadat['lat'], metadat['lon'], metadat['instr_heading']) #cog

    dist_m = humutils.get_dist(lat, lon)
    metadat['dist_m'] = dist_m

    if calc_bearing==1: # recalculate speed, m/s
       ds=np.gradient(np.squeeze(metadat['time_s']))
       dx=np.gradient(np.squeeze(metadat['dist_m']))
       metadat['spd'] = dx[:nrec]/ds[:nrec]

    # theta at 3dB in the horizontal
    theta3dB = np.arcsin(c/(t*(f*1000)))
    #resolution of 1 sidescan pixel to nadir
    ft = (np.pi/2)*(1/theta3dB) #/ (f/455)

    dep_m = humutils.get_depth(metadat['dep_m'][:nrec])

    if old_pyread == 1: #older pyread version

       # port scan
       try:
          if flip_lr==0:
             data_port = data.getportscans().astype('int16')
          else:
             data_port = data.getstarscans().astype('int16')
       except:
          data_port = ''
          print("portside scan not available")

    if data_port!='':

       Zt, ind_port = makechunks_scan(chunkmode, chunkval, metadat, data_port, 0)
       del data_port

       ## create memory mapped file for Z
       shape_port = io.set_mmap_data(sonpath, base, '_data_port.dat', 'int16', Zt)

       ##we are only going to access the portion of memory required
       port_fp = io.get_mmap_data(sonpath, base, '_data_port.dat', 'int16', shape_port)

    if old_pyread == 1: #older pyread version
       # starboard scan
       try:
          if flip_lr==0:
             data_star = data.getstarscans().astype('int16')
          else:
             data_star = data.getportscans().astype('int16')
       except:
          data_star = ''
          print("starboardside scan not available")

    if data_star!='':

       Zt, ind_star = makechunks_scan(chunkmode, chunkval, metadat, data_star, 1)
       del data_star

       # create memory mapped file for Z
       shape_star = io.set_mmap_data(sonpath, base, '_data_star.dat', 'int16', Zt)

       star_fp = io.get_mmap_data(sonpath, base, '_data_star.dat', 'int16', shape_star)

    if 'star_fp' in locals() and 'port_fp' in locals():
       # check that port and starboard are same size
       # and trim if not
       if np.shape(star_fp)!=np.shape(port_fp):
          print("port and starboard scans are different sizes ... rectifying")
          if np.shape(port_fp[0])[1] > np.shape(star_fp[0])[1]:
             tmp = port_fp.copy()
             tmp2 = np.empty_like(star_fp)
             for k in range(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(star_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_port = io.set_mmap_data(sonpath, base, '_data_port2.dat', 'int16', tmp2)
             #shape_star = shape_port.copy()
             shape_star = tuple(np.asarray(shape_port).copy())

             ##we are only going to access the portion of memory required
             port_fp = io.get_mmap_data(sonpath, base, '_data_port2.dat', 'int16', shape_port)

             ind_port = list(ind_port)
             ind_port[-1] = np.shape(star_fp[0])[1]
             ind_port = tuple(ind_port)

          elif np.shape(port_fp[0])[1] < np.shape(star_fp[0])[1]:
             tmp = star_fp.copy()
             tmp2 = np.empty_like(port_fp)
             for k in range(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(port_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_port = io.set_mmap_data(sonpath, base, '_data_star2.dat', 'int16', tmp2)
             #shape_star = shape_port.copy()
             shape_star = tuple(np.asarray(shape_port).copy())

             #we are only going to access the portion of memory required
             star_fp = io.get_mmap_data(sonpath, base, '_data_star2.dat', 'int16', shape_star)

             ind_star = list(ind_star)
             ind_star[-1] = np.shape(port_fp[0])[1]
             ind_star = tuple(ind_star)

    if old_pyread == 1: #older pyread version
       # low-freq. sonar
       try:
          data_dwnlow = data.getlowscans().astype('int16')
       except:
          data_dwnlow = ''
          print("low-freq. scan not available")

    if data_dwnlow!='':

       Zt, ind_low = makechunks_scan(chunkmode, chunkval, metadat, data_dwnlow, 2)
       del data_dwnlow

       # create memory mapped file for Z
       shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', Zt)

       ##we are only going to access the portion of memory required
       dwnlow_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow.dat', 'int16', shape_low)

    if old_pyread == 1: #older pyread version
       # hi-freq. sonar
       try:
          data_dwnhi = data.gethiscans().astype('int16')
       except:
          data_dwnhi = ''
          print("high-freq. scan not available")

    if data_dwnhi!='':

       Zt, ind_hi = makechunks_scan(chunkmode, chunkval, metadat, data_dwnhi, 3)
       del data_dwnhi

       # create memory mapped file for Z
       shape_hi = io.set_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', Zt)

       dwnhi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi.dat', 'int16', shape_hi)

    if 'dwnhi_fp' in locals() and 'dwnlow_fp' in locals():
       # check that low and high are same size
       # and trim if not
       if (np.shape(dwnhi_fp)!=np.shape(dwnlow_fp)) and (chunkmode!=4):
          print("dwnhi and dwnlow are different sizes ... rectifying")
          if np.shape(dwnhi_fp[0])[1] > np.shape(dwnlow_fp[0])[1]:
             tmp = dwnhi_fp.copy()
             tmp2 = np.empty_like(dwnlow_fp)
             for k in range(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(dwnlow_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_low = io.set_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', tmp2)
             #shape_hi = shape_low.copy()
             shape_hi = tuple(np.asarray(shape_low).copy())

             ##we are only going to access the portion of memory required
             dwnhi_fp = io.get_mmap_data(sonpath, base, '_data_dwnhi2.dat', 'int16', shape_hi)

             ind_hi = list(ind_hi)
             ind_hi[-1] = np.shape(dwnlow_fp[0])[1]
             ind_hi = tuple(ind_hi)

          elif np.shape(dwnhi_fp[0])[1] < np.shape(dwnlow_fp[0])[1]:
             tmp = dwnlow_fp.copy()
             tmp2 = np.empty_like(dwnhi_fp)
             for k in range(len(tmp)):
                 tmp2[k] = tmp[k][:,:np.shape(dwnhi_fp[k])[1]]
             del tmp

             # create memory mapped file for Z
             shape_low = io.set_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', tmp2)
             #shape_hi = shape_low.copy()
             shape_hi = tuple(np.asarray(shape_low).copy())

             ##we are only going to access the portion of memory required
             dwnlow_fp = io.get_mmap_data(sonpath, base, '_data_dwnlow2.dat', 'int16', shape_low)

             ind_low = list(ind_low)
             ind_low[-1] = np.shape(dwnhi_fp[0])[1]
             ind_low = tuple(ind_low)

    if old_pyread == 1: #older pyread version
       del data

    if ('shape_port' in locals()) and (chunkmode!=4):
       metadat['shape_port'] = shape_port
       nrec = metadat['shape_port'][0] * metadat['shape_port'][2]
    elif ('shape_port' in locals()) and (chunkmode==4):
       metadat['shape_port'] = shape_port
       nrec = metadat['shape_port'][1]
    else:
       metadat['shape_port'] = ''

    if ('shape_star' in locals()) and (chunkmode!=4):
       metadat['shape_star'] = shape_star
       nrec = metadat['shape_star'][0] * metadat['shape_star'][2]
    elif ('shape_star' in locals()) and (chunkmode==4):
       metadat['shape_star'] = shape_star
       nrec = metadat['shape_star'][1]
    else:
       metadat['shape_star'] = ''

    if ('shape_hi' in locals()) and (chunkmode!=4):
       metadat['shape_hi'] = shape_hi
       #nrec = metadat['shape_hi'][0] * metadat['shape_hi'][2] * 2
    elif ('shape_hi' in locals()) and (chunkmode==4):
       metadat['shape_hi'] = shape_hi
    else:
       metadat['shape_hi'] = ''

    if ('shape_low' in locals()) and (chunkmode!=4):
       metadat['shape_low'] = shape_low
       #nrec = metadat['shape_low'][0] * metadat['shape_low'][2] * 2
    elif ('shape_low' in locals()) and (chunkmode==4):
       metadat['shape_low'] = shape_low
    else:
       metadat['shape_low'] = ''

    #make kml boat trackline
    humutils.make_trackline(lon,lat, sonpath, base)

    if 'port_fp' in locals() and 'star_fp' in locals():

       #if not os.path.isfile(os.path.normpath(os.path.join(sonpath,base+'meta.mat'))):
       if 2>1:
          if bedpick == 1: # auto

             x, bed = humutils.auto_bedpick(ft, dep_m, chunkmode, port_fp, c)

             if len(dist_m)<len(bed):
                dist_m = np.append(dist_m,dist_m[-1]*np.ones(len(bed)-len(dist_m)))

             if doplot==1:
                if chunkmode!=4:
                   for k in range(len(star_fp)):
                      plot_2bedpicks(port_fp[k], star_fp[k], bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], x[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
                else:
                   plot_2bedpicks(port_fp, star_fp, bed, dist_m, x, ft, shape_port, sonpath, 0, chunkmode)

             # 'real' bed is estimated to be the minimum of the two
             bed = np.min(np.vstack((bed[:nrec],np.squeeze(x[:nrec]))),axis=0)
             bed = humutils.runningMeanFast(bed, 3)

          elif bedpick>1: # user prompt

             x, bed = humutils.auto_bedpick(ft, dep_m, chunkmode, port_fp, c)

             if len(dist_m)<len(bed):
                dist_m = np.append(dist_m,dist_m[-1]*np.ones(len(bed)-len(dist_m)))

             # 'real' bed is estimated to be the minimum of the two
             bed = np.min(np.vstack((bed[:nrec],np.squeeze(x[:nrec]))),axis=0)
             bed = humutils.runningMeanFast(bed, 3)

             # manually intervene
             fig = plt.figure()
             ax = plt.gca()
             if chunkmode !=4:
                im = ax.imshow(np.hstack(port_fp), cmap = 'gray', origin = 'upper')
             else:
                im = ax.imshow(port_fp, cmap = 'gray', origin = 'upper')
             plt.plot(bed,'r')
             plt.axis('normal'); plt.axis('tight')

             pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
             x1=map(lambda x: x[0],pts1) # map applies the function passed as
             y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
             plt.close()
             del fig

             if x1 != []: # if x1 is not empty
                tree = KDTree(zip(np.arange(1,len(bed)), bed))
                try:
                   dist, inds = tree.query(zip(x1, y1), k = 100, eps=5, n_jobs=-1)
                except:
                   dist, inds = tree.query(zip(x1, y1), k = 100, eps=5)

                b = np.interp(inds,x1,y1)
                bed2 = bed.copy()
                bed2[inds] = b
                bed = bed2

             if doplot==1:
                if chunkmode!=4:
                   for k in range(len(star_fp)):
                      plot_2bedpicks(port_fp[k], star_fp[k], bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], x[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
                else:
                   plot_2bedpicks(port_fp, star_fp, bed, dist_m, x, ft, shape_port, sonpath, 0, chunkmode)

          else: #manual

             beds=[]

             if chunkmode!=4:
                for k in range(len(port_fp)):
                   raw_input("Bed picking "+str(k+1)+" of "+str(len(port_fp))+", are you ready? 30 seconds. Press Enter to continue...")
                   bed={}
                   fig = plt.figure()
                   ax = plt.gca()
                   im = ax.imshow(port_fp[k], cmap = 'gray', origin = 'upper')
                   pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
                   x1=map(lambda x: x[0],pts1) # map applies the function passed as
                   y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
                   bed = np.interp(np.r_[:ind_port[-1]],x1,y1)
                   plt.close()
                   del fig
                   beds.append(bed)
                   extent = np.shape(port_fp[k])[0]
                bed = np.asarray(np.hstack(beds),'float')
             else:
                raw_input("Bed picking - are you ready? 30 seconds. Press Enter to continue...")
                bed={}
                fig = plt.figure()
                ax = plt.gca()
                im = ax.imshow(port_fp, cmap = 'gray', origin = 'upper')
                pts1 = plt.ginput(n=300, timeout=30) # it will wait for 200 clicks or 60 seconds
                x1=map(lambda x: x[0],pts1) # map applies the function passed as
                y1=map(lambda x: x[1],pts1) # first parameter to each element of pts
                bed = np.interp(np.r_[:ind_port[-1]],x1,y1)
                plt.close()
                del fig
                beds.append(bed)
                extent = np.shape(port_fp)[1]
                bed = np.asarray(np.hstack(beds),'float')

          # now revise the depth in metres
          dep_m = (1/ft)*bed

          if doplot==1:
             if chunkmode!=4:
                for k in range(len(star_fp)):
                   plot_bedpick(port_fp[k], star_fp[k], (1/ft)*bed[ind_port[-1]*k:ind_port[-1]*(k+1)], dist_m[ind_port[-1]*k:ind_port[-1]*(k+1)], ft, shape_port, sonpath, k, chunkmode)
             else:
                plot_bedpick(port_fp, star_fp, (1/ft)*bed, dist_m, ft, shape_port, sonpath, 0, chunkmode)

          metadat['bed'] = bed[:nrec]

    else:
       metadat['bed'] = dep_m[:nrec]*ft

    metadat['heading'] = metadat['heading'][:nrec]
    metadat['lon'] = lon[:nrec]
    metadat['lat'] = lat[:nrec]
    metadat['dist_m'] = dist_m[:nrec]
    metadat['dep_m'] = dep_m[:nrec]
    metadat['pix_m'] = 1/ft
    metadat['bed'] = metadat['bed'][:nrec]
    metadat['c'] = c
    metadat['t'] = t
    if model==2:
       metadat['f'] = f*2
    else:
       metadat['f'] = f

    metadat['spd'] = metadat['spd'][:nrec]
    metadat['time_s'] = metadat['time_s'][:nrec]
    metadat['e'] = metadat['e'][:nrec]
    metadat['n'] = metadat['n'][:nrec]
    metadat['es'] = metadat['es'][:nrec]
    metadat['ns'] = metadat['ns'][:nrec]
    try:
       metadat['caltime'] = metadat['caltime'][:nrec]
    except:
       metadat['caltime'] = metadat['caltime']

    savemat(os.path.normpath(os.path.join(sonpath,base+'meta.mat')), metadat ,oned_as='row')

    f = open(os.path.normpath(os.path.join(sonpath,base+'rawdat.csv')), 'wt')
    writer = csv.writer(f)
    writer.writerow( ('longitude', 'latitude', 'easting', 'northing', 'depth (m)', 'distance (m)', 'instr. heading (deg)', 'heading (deg.)' ) )
    for i in range(0, nrec):
       writer.writerow(( float(lon[i]),float(lat[i]),float(es[i]),float(ns[i]),float(dep_m[i]),float(dist_m[i]), float(metadat['instr_heading'][i]), float(metadat['heading'][i]) ))
    f.close()

    del lat, lon, dep_m #, dist_m

    if doplot==1:

       plot_pos(sonpath, metadat, es, ns)

       if 'dwnlow_fp' in locals():

          plot_dwnlow(dwnlow_fp, chunkmode, sonpath)

       if 'dwnhi_fp' in locals():

          plot_dwnhi(dwnhi_fp, chunkmode, sonpath)

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