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
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])
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)
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],:]
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]
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