Пример #1
0
def load_flowline(glacier,shapefilename='center_flowline',filt_len=2.0e3,verticaldatum='geoid',bedsource='cresis',bedmodel='aniso',bedsmoothing=4,dx=20):

  '''
  x,y,zb_filt,dists = load(glacier,shapefilename='center_flowline')
  
  Load glacier flowline. This script is mostly to keep everything consistent (distance 
  along flowline, chosen bed profile,etc.
  
  Inputs:
  glacier: glacier name
  shapefilename: shapefile to use for the flowline
  filt_len: filter length (in meters) for the bed profile
  verticaldatum: geoid or ellipsoid
  dx: distance between points
  
  Outputs:
  x,y: x,y coordinates of flowline
  zb_filt: bed profile for flowline
  '''

  if glacier == 'Helheim':
    file1 = 'helheim_'
  elif glacier == 'Kanger':
    file1 = 'kanger_'
  elif glacier == 'Midgaard':
    file1 = 'midgaard_'
  else:
    sys.exit("Unknown glacier.") 
  file_flowline_in = os.path.join(os.getenv("DATA_HOME"),"ShapeFiles/Glaciers/Flowlines/"+glacier+"/"+file1+shapefilename)

  
  flowline = meshlib.shp_to_xy(file_flowline_in)
  d = distlib.transect(flowline[:,0],flowline[:,1])

  # Set uniform spacing between nodes along flowline
  dists_old = np.linspace(0,np.max(d),np.max(d)/dx)
  x = np.interp(dists_old,d,flowline[:,0])
  y = np.interp(dists_old,d,flowline[:,1])
  
  # Get new distances
  dists = distlib.transect(x,y)

  # Get average terminus position
  time1 = 2008.0
  time2 = 2016.0
  
  # Get terminus positions so that we can set distance along flowline 
  # relative to the average terminus position
  terminus_val, terminus_time = icefrontlib.distance_along_flowline(x,y,dists,glacier,type='icefront',time1=time1,time2=time2)

  # Average terminus position
  terminus = np.mean(terminus_val)

  # Set dists relative to average terminus position
  dists = dists-terminus

  # Find bed elevation
  if (glacier == 'Helheim') and (bedsource == 'smith'):
    zb = bedlib.smith_at_pts(x,y,glacier,model=bedmodel,smoothing=bedsmoothing,verticaldatum=verticaldatum)
  elif bedsource == 'morlighem':
    zb = bedlib.morlighem_pts(x,y,verticaldatum=verticaldatum)
  elif (glacier == 'Kanger' and (bedsource != 'morlighem')) or (bedsource == 'cresis'):
    cresis = bedlib.cresis('all',glacier,verticaldatum=verticaldatum)
    if glacier == 'Helheim':
      cresis2001 = bedlib.cresis('2001',glacier,verticaldatum=verticaldatum)
      cresis = np.row_stack([cresis,cresis2001])
    cutdist = 200.
    dcresis = []
    zcresis = []
    tcresis = []
    for i in range(0,len(cresis[:,0])):
      mindist = np.min(np.sqrt((cresis[i,0]-x)**2+(cresis[i,1]-y)**2))
      if mindist < cutdist:
        minind = np.argmin(np.sqrt((cresis[i,0]-x)**2+(cresis[i,1]-y)**2))
        dcresis.append(dists[minind])
        zcresis.append(cresis[i,2])
        tcresis.append(cresis[i,4])

    ind = np.argsort(dcresis)
    dcresis = np.array(dcresis)[ind]
    zcresis = np.array(zcresis)[ind]
    zb = np.interp(dists,dcresis,zcresis)

  if filt_len != 'none':
    ind = np.where(~(np.isnan(zb)))[0]
    zb_filt = np.zeros_like(zb)
    zb_filt[:] = float('nan')
    cutoff=(1/filt_len)/(1/(np.diff(dists[1:3])*2))
    b,a=scipy.signal.butter(4,cutoff,btype='low')
    zb_filt[ind] = scipy.signal.filtfilt(b,a,zb[ind])
  else:
    zb_filt = zb
    
  if (glacier == 'Kanger') and (shapefilename=='flowline_flightline'):
    ind = np.where(dists > 3000.)[0]
    zb_filt[ind] = float('nan')
  elif (glacier == 'Helheim') and (shapefilename=='flowline_flightline'):
    ind = np.where(dists > 3900.)[0]
    zb_filt[ind] = float('nan')
    

  return x,y,zb_filt,dists
Пример #2
0
xdem, ydem, zdem, timedem, errordem = zslib.dem_grid(glacier,
                                                     xmin,
                                                     xmax,
                                                     ymin,
                                                     ymax,
                                                     years='all',
                                                     verticaldatum='geoid',
                                                     return_error=True)

####################################
# Get bed elevations near flowline #
####################################

# Get radar thicknesses close to flightline
cresis = bedlib.cresis('all', glacier)
if glacier == 'Helheim':
    cresis2001 = bedlib.cresis('2001', glacier)
    cresis = np.row_stack([cresis, cresis2001])

cutoff = 200.
dcresis = []
zcresis = []
tcresis = []
for i in range(0, len(cresis[:, 0])):
    mindist = np.min(np.sqrt((cresis[i, 0] - x)**2 + (cresis[i, 1] - (y))**2))
    if mindist < cutoff:
        minind = np.argmin(
            np.sqrt((cresis[i, 0] - x)**2 + (cresis[i, 1] - (y))**2))
        dcresis.append(dists[minind])
        zcresis.append(cresis[i, 2])
Пример #3
0
elif glacier == 'Kanger':
    xmin = 480000.0
    xmax = 506000.0
    ymin = -2302000.0
    ymax = -2280000.0

# Directories
DIRX = os.path.join(os.getenv("DATA_HOME"),
                    "ShapeFiles/Glaciers/3D/" + glacier + "/")

# Mesh extent
#exterior = meshlib.shp_to_xy(DIRX+"glacier_extent_normal")
#exterior_nofront = meshlib.shp_to_xy(DIRX+"glacier_extent_nofront")

# Load CreSIS radar picks
cresis_2001 = bedlib.cresis('2001', glacier, verticaldatum='geoid')
cresis_all = bedlib.cresis('all', glacier, verticaldatum='geoid')
ind = np.where(cresis_all[:, 2] < 0)[0]

# Load CreSIS grid
xCre, yCre, zCre = bedlib.cresis_grid(glacier, verticaldatum='geoid')

# Morlighem bed
xMor, yMor, zMor = bedlib.morlighem_grid(xmin, xmax, ymin, ymax, 'geoid')
cresis_all_zMor = bedlib.morlighem_pts(cresis_all[ind, 0], cresis_all[ind, 1],
                                       glacier, 'geoid')
cresis_2001_zMor = bedlib.morlighem_pts(cresis_2001[:, 0], cresis_2001[:, 1],
                                        glacier, 'geoid')

# Make some plots
plt.figure(1)
Пример #4
0
import numpy as np
import vellib, icefrontlib, bedlib, zslib, distlib
import matplotlib.pyplot as plt

##########
# Inputs #
##########
time1=2009
time2=2015

#############
# Load data #
#############

# Load Helheim bed
bed = bedlib.cresis('2001')
bed = bed[17:,:] #throw out points that don't follow a flowline
dists = distlib.transect(bed[:,0],bed[:,1])-5165 # Last value to offset distances so similar zero point as that in "velocity_vs_terminus"

# Terminus positions
term, termt = icefrontlib.distance_along_flowline(bed[:,0],bed[:,1],dists,'icefront')
rift, riftt = icefrontlib.distance_along_flowline(bed[:,0],bed[:,1],dists,'rift')

# Load elevations
elev,elevt = zslib.worldview_at_pts(bed[:,0],bed[:,1],32,[])

# Calculate divergence
v,vx,vy,divx,divy,vt = vellib.divergence_at_eulpoints(bed[:,0],bed[:,1])
indices = np.where((vt > time1) & (vt < time2))
v=v[indices[0],:]
vx=vx[indices[0],:]
Пример #5
0
def fluxgate(glacier,
             fluxgate_filename,
             bedsource='smith',
             dl=20.0,
             timing='velocity'):
    '''
  
  time, sumQ, Hbar, ubar, error = fluxgate(glacier,fluxgate_filename,bedsource='smith',dl=20.0,timing='velocity')
  
  Inputs:
  glacier: glacier name
  fluxgate_filename: fluxgate filename
  bedsource: should be use CreSIS radar transects or morlighem/smith bed DEM to define the bed elevation?
  dl: size of blocks for integrating ice flux across fluxgate
  timing: calculate flux either when we have velocities ('velocity') or surface elevaions ('elevation')
  '''

    # Get Shapefiles for flux gates and for glacier extent (so we can calculate surface area accurately)
    DIR = os.path.join(os.getenv("DATA_HOME"),
                       "ShapeFiles/FluxGates/" + glacier + "/")
    gate_sf = shapefile.Reader(DIR + fluxgate_filename)

    # Get end points for flux gates
    gate_pts = np.array(gate_sf.shapes()[0].points)
    sortind = np.argsort(gate_pts[:, 1])
    gate_pts = gate_pts[sortind]

    # Calculate length of flux gates (i.e., the "width" of glacier)
    L = distlib.transect(gate_pts[:, 0], gate_pts[:, 1])

    # Get coordinates of points along flux gate
    l = np.linspace(0, L[-1], np.ceil(L[-1] / dl) + 1)
    dl = l[1] - l[0]
    l = l[0:-1] + dl / 2
    x = np.interp(l, L, gate_pts[:, 0])
    y = np.interp(l, L, gate_pts[:, 1])

    # Get surface elevations
    if glacier == 'Midgaard' or glacier == 'Fenris':
        zs_gimp = zslib.gimp_at_pts(x, y, glacier, verticaldatum='ellipsoid')
        zs_error = np.zeros_like(zs_gimp)
        halfind = int(len(x) / 2)  # Index for halfway along fluxgate
        zpt_atm, zptstd_atm, time_atm = zslib.atm_at_pts(
            [x[halfind]], [y[halfind]],
            glacier,
            maxdist=200,
            verticaldatum='ellipsoid')

        #zs_all = zs_gimp
        #ztime = []
        ztime = time_atm
        zs_all = np.zeros([len(time_atm), len(x)])
        for i in range(0, len(time_atm)):
            diff = zpt_atm[i] - zs_gimp[halfind]
            zs_all[i, :] = zs_gimp + diff
    else:
        zs_all, zs_error, ztime = zslib.dem_at_pts(x,
                                                   y,
                                                   glacier,
                                                   verticaldatum='ellipsoid',
                                                   method='linear')

    # Get bed elevation along flux gates
    if bedsource == 'morlighem':
        print "Using Morlighem bed DEM, should maybe be changed to CreSIS radar transects or Smith bed DEM"
        zb = bedlib.morlighem_pts(x, y, verticaldatum='ellipsoid')
        if glacier == 'Midgaard':
            # The Morlighem bed DEM is HORRIBLE for Midgaard. If it was right, the surface would
            # currently be below the bed. Unfortunately there aren't any better options (very few
            # ice thickness measurements), so what I'm doing is adjusting the morlighem bed DEM
            # by a known ice thickness measurements from ~1 km downstream, which has the ice thickness
            # at 110 m in 2013 with a surface elevation of 253 m.
            zpt_2013 = np.interp(2013.25, time_atm, zpt_atm[:, 0])
            diff = (zpt_2013 - 150) - zb[halfind]
            zb = zb + diff
    elif bedsource == 'smith':
        print "Using Smith bed DEM"
        zb = bedlib.smith_at_pts(x, y, glacier, verticaldatum='ellipsoid')
    else:
        print "Using CreSIS radar products"
        cresis_all = bedlib.cresis('all', glacier, verticaldatum='ellipsoid')

        # Find radar pick indices for flux gate
        zb = np.zeros_like(x)
        # Find points that are within 200~m of CreSIS transect for interpolation
        ind = []
        for i in range(0, len(x)):
            d = np.min(
                np.sqrt((x[i] - cresis_all[:, 0])**2 +
                        (y[i] - cresis_all[:, 1])**2))
            if d < 200.0:
                ind.append(i)
        zb[ind] = scipy.interpolate.griddata(cresis_all[:, 0:2], cresis_all[:,
                                                                            2],
                                             (x[ind], y[ind]))
        f = scipy.interpolate.interp1d(l[ind],
                                       zb[ind],
                                       kind='cubic',
                                       bounds_error=False)
        fex = extrap1d(f)
        zb[zb == 0] = fex(l[zb == 0])
        filt_len = 500.0
        cutoff = (1 / filt_len) / (1 / ((l[1] - l[0]) * 2))
        b, a = scipy.signal.butter(4, cutoff, btype='low')
        zb = scipy.signal.filtfilt(b, a, zb)

    # Get velocities
    if glacier == 'Fenris':
        vpt, tpt, ept, vxpt, vypt = vellib.howat_optical_at_pts(
            x, y, 'Helheim', xy_velocities='True')
        tpt = tpt[:, 0]
    else:
        vpt, tpt, ept, vxpt, vypt = vellib.velocity_at_eulpoints(
            x, y, glacier, data='TSX', xy_velocities='True')

    # Get normal to fluxgate so we can calculate flux through it
    xperp = np.zeros(len(l))
    yperp = np.zeros(len(l))
    for i in range(0, len(l) - 1):
        xperp[i + 1] = -(-y[i + 1] + y[i]) / np.sqrt((y[i + 1] - y[i])**2 +
                                                     (x[i + 1] - x[i])**2)
        yperp[i + 1] = -(x[i + 1] - x[i]) / np.sqrt((y[i + 1] - y[i])**2 +
                                                    (x[i + 1] - x[i])**2)
    xperp[0] = xperp[1]
    yperp[0] = yperp[1]

    # Find dates with complete velocity profiles. We will use these profiles to create a
    # "shape factor" to fill in discontinuous velocity records.
    ind = []
    for i in range(0, len(tpt)):
        nans = np.where(np.isnan(vxpt[i, :]))[0]
        if len(nans) < 1:
            ind.append(i)
    if len(ind) < 1:
        ind = range(0, len(tpt))

    # Velocity shape factor
    sf = np.nanmean(
        abs(xperp * vxpt[ind, :] + yperp * vypt[ind, :]), 0) / np.nanmax(
            np.nanmean(abs(xperp * vxpt[ind, :] + yperp * vypt[ind, :]), 0))
    vperp = (xperp * vxpt + yperp * vypt)
    vperp[:, 0] = sf[0] * np.nanmax(vperp, 1)
    vperp[:, -1] = sf[-1] * np.nanmax(vperp, 1)
    ind = np.where(vperp < 0)
    vperp[ind] = 0.0

    midind = np.argmax(np.nanmean(vperp, axis=0))

    if timing == 'velocity':
        # Find DEMs where more than 90% of the data points are nonnan.
        if len(ztime) > 0:
            ind_DEM = []
            for i in range(0, len(ztime)):
                nonnan = np.where(~(np.isnan(zs_all[i, :])))[0]
                if len(nonnan) > (9. / 10.) * len(l):
                    ind_DEM.append(i)

        Q = np.zeros_like(vperp)  # actual fluxes
        Q[:, :] = float('nan')
        allH = np.zeros_like(vperp)  # actual fluxes
        allH[:, :] = float('nan')
        allU = np.zeros_like(vperp)  # actual fluxes
        allU[:, :] = float('nan')
        time = tpt
        error = np.zeros_like(time)
        error[:] = float('nan')
        ubar = np.zeros_like(time)
        ubar[:] = float('NaN')
        width = np.zeros_like(time)
        width[:] = float('NaN')
        Hbar = np.zeros([len(time), 2])
        Hbar[:, :] = float('NaN')
        Across = np.zeros_like(time)
        Across[:] = float('nan')
        for i in range(0, len(time)):
            # Find places where we have no surface velocities
            nans_vperp = np.where(np.isnan(vperp[i, :]))[0]
            if len(nans_vperp) < 1.0 / 3.0 * len(l):
                # If the number of locations without surface velocities is small, let's use the known
                # surface velocities to interpolate.
                nonnans_vperp = np.where(~(np.isnan(vperp[i, :])))[0]
                vperp_errors = np.zeros(len(l))

                if len(ztime) > 0:
                    # Get surface elevation for that timestep
                    zs = np.zeros(len(l))
                    zs_error_ind = np.zeros(len(l))

                    # Linearly interpolate surface elevations from the available ones.
                    zs = np.zeros_like(l)
                    for j in range(0, len(zs)):
                        nonnan = np.where(~(np.isnan(zs_all[ind_DEM, j])))[0]
                        newind = [ind_DEM[k] for k in nonnan]
                        zs[j] = np.interp(tpt[i], ztime[newind], zs_all[newind,
                                                                        j])
                else:
                    zs = zs_all

                zs_error_ind = zs_error

                # Interpolate surface velocities using a shape factor for the
                # cross-sectional velocity profile
                f = np.arange(
                    np.nanmin(np.nanmax(vperp[:, :], axis=1)) - 500,
                    np.nanmax(np.nanmax(vperp[:, :], axis=1)) + 500, 10)
                mindiff = 1e20
                for j in range(0, len(f)):
                    diff = np.sqrt(
                        np.mean(sf[nonnans_vperp] * f[j] -
                                vperp[i, nonnans_vperp])**2)
                    if diff < mindiff:
                        mindiff = float(diff)
                        fbest = int(j)
                vperp[i, nans_vperp] = sf[nans_vperp] * f[fbest]

                # Set velocity errors
                vperp_errors[nonnans_vperp] = vperp[i, nonnans_vperp] * 0.03
                vperp_errors[nans_vperp] = vperp[i, nans_vperp] * 0.1

                # Let's try filtering data before calculating ice flux
                filt_len = 300.

                cutoff = (1 / filt_len) / (1 / (np.diff(l[1:3]) * 2))
                b, a = scipy.signal.butter(4, cutoff, btype='low')
                zs_filt = scipy.signal.filtfilt(b, a, zs)
                vperp_filt = scipy.signal.filtfilt(b, a, vperp[i, :])

                # Calculate fluxes, only where zs > zb
                Q[i, :] = 0.0
                ind = np.where((zs_filt - zb > 0) & (vperp_filt > 0))[0]
                Q[i, ind] = ((vperp_filt[ind]) * (zs_filt[ind] - zb[ind]) * dl)

                # Get average surface elevations and ice flow velocities for fluxgate
                sf_flux = Q[i, :] / np.nanmax(Q[i, :])
                #Hbar[i,0] = np.nansum(sf_flux*(zs_filt-zb))/np.sum(sf_flux)
                Hbar[i, 0] = np.mean(zs_filt[midind - 200:midind + 201] -
                                     zb[midind - 200:midind + 201])
                Hbar[i, 1] = np.mean(zs_error_ind[midind - 200:midind +
                                                  201]) / np.sqrt(2000. / 300.)
                ubar[i] = np.mean(vperp_filt[midind - 200:midind + 201])
                #ubar[i] = np.nansum(sf_flux*(vperp_filt))/np.sum(sf_flux)
                Across[i] = np.sum((zs_filt[ind] - zb[ind]) * dl)

                allH[i, ind] = zs_filt[ind] - zb[ind]
                allU[i, ind] = (vperp_filt[ind])

                # Calculate errors
                ubar_error = np.sqrt(1 / (np.sum(
                    np.mean(1 / vperp_errors)**2 * np.ones(int(L[1] / 500.)))))
                hbar_error = np.sqrt(1 / (np.sum(
                    np.mean(1 / zs_error_ind)**2 * np.ones(int(L[1] / 32.)))))
                error[i] = np.sum(
                    Q[i, :]) * np.sqrt((ubar_error / ubar[i])**2 +
                                       (hbar_error / Hbar[i, 0])**2)

    elif timing == 'elevation':
        time = ztime
        Q = np.zeros([len(time), len(l)])  # actual fluxes
        Q[:, :] = float('NaN')
        error = np.zeros_like(time)
        error[:] = float('nan')
        ubar = np.zeros_like(time)
        ubar[:] = float('NaN')
        Hbar = np.zeros([len(time), 2])
        Hbar[:, :] = float('NaN')
        Across = np.zeros_like(time)
        Across[:] = float('nan')
        for i in range(0, len(time)):
            nonnans = np.where(~(np.isnan(zs_all[i, :])))[0]
            nans = np.where((np.isnan(zs_all[i, :])))[0]
            if len(nonnans) > (9. / 10) * len(l):
                zs_ind = zs_all[i, :]
                zs_ind[nans] = np.interp(l[nans], l[nonnans], zs_all[i,
                                                                     nonnans])
                ind = np.argmin(abs(time[i] - tpt))
                if (time[i] - tpt[ind]) < 1 / 12.:
                    nonnans = np.where(~(np.isnan(vperp[ind, :])))[0]
                    nans = np.where(np.isnan(vperp[ind, :]))[0]

                    vperp_ind = vperp[ind, :]
                    vperp_ind[nans] = sf[nans] * np.nanmax(vperp[i, :])  #

                    # Calculate fluxes
                    Q[i, :] = (vperp_ind * (zs_ind - zb) * dl)

                    # We don't want negative fluxes so let's toss them out.
                    Q[i, zs_ind < zb] = 0

                    # Get average surface elevations and ice flow velocities for fluxgate
                    ind = np.where(zs_ind - zb > 0)[0]
                    Hbar[i, 0] = np.mean(zs_ind[midind - 200:midind + 201] -
                                         zb[midind - 200:midind + 201])
                    Hbar[i, 1] = zs_error[i] / np.sqrt(2000. / 200.)
                    ubar[i] = np.mean(vperp_ind[midind - 200:midind + 201])
                    Across[i] = np.sum((zs_ind[ind] - zb[ind]) * dl)

    # Add up fluxes along glacier width
    sumQ = np.sum(Q, 1)

    return time, sumQ, Hbar, ubar, error, L[1]
Пример #6
0
def extent(xs,ys,zs,ztime,glacier,rho_i=917.0,rho_sw=1020.0,bedsource='cresis',verticaldatum='geoid'):

  '''
  This function finds the height above (or below) flotation for an array of surface elevations,
  according to the Morlighem bed DEM or CreSIS radar picks. Right now it's only set up to 
  work for cresis radar picks.
  
  Inputs:
  xs,ys,zs,time from zslib.dem_grid
  glacier: name of glacier
  rho_i: ice density
  rho_sw: seawater density
  bedsource: cresis or morlighem
  
  Outputs:
  xf,yf,zabovefloat: height above (or below flotation) at points xf,yf
  '''
  
  # Find bed elevations
  if bedsource=='cresis':
    cresis = bedlib.cresis('all',glacier,verticaldatum,cleanup=True)
    cresis2001 = bedlib.cresis('2001',glacier,verticaldatum)
    cresis = np.row_stack([cresis[cresis[:,2]<-50.0,:],cresis2001[cresis2001[:,2]<-50.0,:]])
  else:
    print "need to work on morlighem"
  
  # Find flotation height
  zfloat = height(cresis[:,2],rho_i=rho_i,rho_sw=rho_sw)
  xf = cresis[:,0]
  yf = cresis[:,1]
  
  # Calculate height above flotation through time
  try:
    N = len(ztime)
  except: 
    N = 1
  zabovefloat=np.zeros([len(zfloat),N])
  zabovefloat[:,:] = float('NaN')
  for i in range(0,N): 
  
    # Get glacier extent so we're only checking if the glacier is floating where there is glacier ice
    if N == 1: # no iteration if only one DEM
      extent = glaclib.load_extent(glacier,ztime)
      dem = scipy.interpolate.RegularGridInterpolator([ys,xs],zs[:,:],bounds_error = False,method='linear',fill_value=float('nan')) 
    else:
      extent = glaclib.load_extent(glacier,ztime[i])
      dem = scipy.interpolate.RegularGridInterpolator([ys,xs],zs[:,:,i],bounds_error = False,method='linear',fill_value=float('nan')) 
    
    # Check what points are located on glacier ice
    box = path.Path(extent[:,0:2])
  
    # Find indices in the grid that fall within the fluxbox
    inside = box.contains_points(np.column_stack([cresis[:,0:2]]))
    
    # Current surface elevation
    zs_on_zb = dem((cresis[:,1],cresis[:,0]))
    
    # Find height above flotation
    zabovefloat[inside,i] = zs_on_zb[inside]-zfloat[inside]
    
  return xf,yf,zabovefloat