def width(time1, time2, glacier, type='icefront', datatypes='all'): ''' termt,termwidth = width(time1,time2,glacier,type='icefront') Calculate calving-front width (i.e., integrate distances along ice front). Inputs: time1,time2: load terminus positions from time1 to time2 glacier: glacier name type: icefront or rift Outputs: termwidth: width of calving front at termt ''' # Load desired values for "glacier" termx, termy, termt = load_all(time1, time2, glacier, type='icefront', datatypes=datatypes) # Calculate width for each time termwidth = np.zeros(len(termt)) for i in range(0, len(termt)): dists = distlib.transect(termx[:, i], termy[:, i]) termwidth[i] = np.nanmax(dists) return termt, termwidth
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
def load_extent_timeseries(glacier,time1,time2,dt,nofront_shapefile='glacier_extent_nofront',datatypes=['Landsat','TSX','WV']): ''' time, xextents, yxextents, bounds = load_extent_timeseries(glacier,time1, time2,dt,nofront_shapefile='glacier_extent_nofront', datatypes=['Landsat','TSX','WV']) Interpolates ice-front positions from picked ice-front positions to create a timeseries of meshes to be used in the terminus-driven model. Inputs: glacier : glacier name (Helheim, Kanger) time1 : fractional start time for timeseries time2 : fractional end time for timeseries dt : timestep nofront_shapefile : nofront shapefile name for mesh extent datatypes : satellite image types for picked ice fronts Outputs: time : interpolated time between time1,time2 with timestep dt xextents : 2-d array of x-coordinates of extents yextents : 2-d array of y-coordinates of extents bounds : boundary numbers for extents ''' # Glacier extent with no ice front extent = meshlib.shp_to_xy(os.path.join(os.getenv("DATA_HOME"),"ShapeFiles/Glaciers/3D/"+glacier+"/"+nofront_shapefile)) if extent[1,1] > extent[0,1]: extent = np.flipud(extent) xextent = extent[:,0] yextent = extent[:,1] bound_extent = extent[:,2] # Interpolate glacier extent to a finer grid to make ice-front interpolation easier dextent = distlib.transect(xextent,yextent) #dextent = np.arange(0,dold[-1],20.0) #xextent = np.interp(dextent,dold,xextent) #yextent = np.interp(dextent,dold,yextent) #f = scipy.interpolate.interp1d(dold,bound,kind='nearest') #bound = f(dextent) extent = LineString(np.column_stack([extent[:,0:2]])) # Load all ice front positions for that time period termx,termy,termt = icefrontlib.load_all(time1-0.5,time2+0.5,glacier,type='icefront',datatypes=datatypes) # In case we have multiple ice front picks for the same day, we want to # use only one of those for continuity [junk,ind] = np.unique(termt,return_index=True) termt = np.array(termt)[ind] termx = termx[:,ind] termy = termy[:,ind] # Load a velocity profile to use as interpolation direction to figure out ice-front position # on timesteps that fall between picked ice fronts x,y,u = geotifflib.read(os.path.join(os.getenv("DATA_HOME"),"Velocity/TSX/"+glacier+"/TIF/all-2008-2016_vx.tif")) x,y,v = geotifflib.read(os.path.join(os.getenv("DATA_HOME"),"Velocity/TSX/"+glacier+"/TIF/all-2008-2016_vy.tif")) fu = scipy.interpolate.RegularGridInterpolator((y,x),u) fv = scipy.interpolate.RegularGridInterpolator((y,x),v) # Get ice-front position for each timestep time = np.arange(time1,time2+dt,dt) timeseries_x = np.zeros([len(termx[:,0]),len(time)]) timeseries_y = np.zeros([len(termx[:,0]),len(time)]) timeseries_advance = np.zeros([len(termx[:,0]),len(time)]) timeseries_dist = np.zeros([len(termx[:,0]),len(time)]) timeseries_x[:,:] = float('nan') timeseries_y[:,:] = float('nan') timeseries_advance[:,:] = float('nan') timeseries_dist[:,:] = float('nan') xextents = np.zeros([len(termx[:,0])+len(xextent),len(time)]) yextents = np.zeros([len(termx[:,0])+len(xextent),len(time)]) bounds = np.zeros([len(termx[:,0])+len(xextent),len(time)]) for i in range(0,len(time)): # Find picked ice-front positions for before and after timestep for the interpolation ind = np.argmin(abs(time[i]-termt)) if termt[ind] < time[i]: ind1 = ind ind2 = ind+1 else: ind1 = ind-1 ind2 = ind # Fractional time between ind1,ind2 to use for interpolation frac = (time[i]-termt[ind1])/(termt[ind2]-termt[ind1]) # Get picked ice-front positions that we will use for the interpolation nonnan = np.where(~(np.isnan(termx[:,ind1])))[0] termx1 = termx[nonnan,ind1] termy1 = termy[nonnan,ind1] nonnan = np.where(~(np.isnan(termx[:,ind2])))[0] termx2 = termx[nonnan,ind2] termy2 = termy[nonnan,ind2] if termy1[-1] > termy1[0]: termx1 = np.flipud(termx1) termy1 = np.flipud(termy1) if termy2[-1] > termy2[0]: termx2 = np.flipud(termx2) termy2 = np.flipud(termy2) # Get locations where interpolate ice front intersects the glacier extent # First, get intersection pts for two closest ice-front positions in time term1 = LineString(np.column_stack([termx1,termy1])) intersect = extent.intersection(term1) try: if len(intersect) == 2: if intersect[0].y > intersect[1].y: top1 = [intersect[0].x,intersect[0].y] bot1 = [intersect[1].x,intersect[1].y] else: top1 = [intersect[1].x,intersect[1].y] bot1 = [intersect[0].x,intersect[0].y] else: print "Need to look at date ", datelib.fracyear_to_date(termt[ind1]) except: print "Need to look at date ", datelib.fracyear_to_date(termt[ind1]) term2 = LineString(np.column_stack([termx2,termy2])) intersect = extent.intersection(term2) try: if len(intersect) == 2: if intersect[0].y > intersect[1].y: top2 = [intersect[0].x,intersect[0].y] bot2 = [intersect[1].x,intersect[1].y] else: top2 = [intersect[1].x,intersect[1].y] bot2 = [intersect[0].x,intersect[0].y] else: print "Need to look at date ", datelib.fracyear_to_date(termt[ind2]) except: print "Need to look at date ", datelib.fracyear_to_date(termt[ind2]) # Now find new intersection points if top1[0] < top2[0]: # advancing on this side ind_top = np.where((xextent > top1[0]) & (xextent < top2[0]) & (abs(top1[1]-yextent) < 500.))[0] sortind = np.argsort(xextent[ind_top]) xtops = np.r_[top1[0],xextent[ind_top[sortind]],top2[0]] ytops = np.r_[top1[1],yextent[ind_top[sortind]],top2[1]] dtops = distlib.transect(xtops,ytops) dtop = dtops[-1]*frac elif top1[0] > top2[0]: # retreating on this side ind_top = np.where((xextent < top1[0]) & (xextent > top2[0]) & (abs(top1[1]-yextent) < 500.))[0] sortind = np.argsort(xextent[ind_top]) xtops = np.r_[top2[0],xextent[ind_top[sortind]],top1[0]] ytops = np.r_[top2[1],yextent[ind_top[sortind]],top1[1]] dtops = distlib.transect(xtops,ytops) dtop = dtops[-1]*(1-frac) else: print "not advancing or retreating on top" xtop = np.interp(dtop,dtops,xtops) ytop = np.interp(dtop,dtops,ytops) if bot1[0] < bot2[0]: # advancing on this side ind_bot = np.where((xextent > bot1[0]) & (xextent < bot2[0]) & (abs(bot1[1]-yextent) < 500.))[0] sortind = np.argsort(xextent[ind_bot]) xbots = np.r_[bot1[0],xextent[ind_bot[sortind]],bot2[0]] ybots = np.r_[bot1[1],yextent[ind_bot[sortind]],bot2[1]] dbots= distlib.transect(xbots,ybots) dbot = (dbots[-1])*frac elif bot1[0] > bot2[0]: # retreating on this side ind_bot = np.where((xextent < bot1[0]) & (xextent > bot2[0]) & (abs(bot1[1]-yextent) < 500.))[0] sortind = np.argsort(xextent[ind_bot]) xbots = np.r_[bot2[0],xextent[ind_bot[sortind]],bot1[0]] ybots = np.r_[bot2[1],yextent[ind_bot[sortind]],bot1[1]] dbots= distlib.transect(xbots,ybots) dbot = (dbots[-1])*(1-frac) else: print "not advancing or retreating on bot" xbot = np.interp(dbot,dbots,xbots) ybot = np.interp(dbot,dbots,ybots) # Now that we know the bottom and top points (extent of the ice front), we can start # calculating the shape, again based on linear interpolation # May need to change next expression to find indices between the sidewalls for Kanger, # but this should work for Helheim ind_term1 = np.where((termy1 > bot1[1]) & (termy1 < top1[1]))[0] icefront_x = [] icefront_y = [] advance = [] icefront_x.append(xtop) icefront_y.append(ytop) if i > 0: nonnan = np.where(~(np.isnan(xextents[:,i-1])))[0] extentpath = Path(np.column_stack([xextents[nonnan,i-1],yextents[nonnan,i-1]])) if extentpath.contains_point([xtop,ytop]) or (xtop < xtop_old): sign = -1 else: sign = 1 advance.append(sign*distlib.between_pts(xtop,ytop,xtop_old,ytop_old)) else: advance.append(0) for j in ind_term1: # Get velocities to create a line, to interpolate between ice fronts uj = fu((termy1[j],termx1[j])) vj = fv((termy1[j],termx1[j])) # Create flowline that intersects that point of the ice front xunit = uj/(np.sqrt(uj**2+vj**2)) yunit = vj/(np.sqrt(uj**2+vj**2)) b = termy1[j] - (yunit/xunit)*termx1[j] flowlinex = np.arange(-3000.,3005.,10) + termx1[j] flowliney = (yunit/xunit)*flowlinex + b flowline = LineString(np.column_stack([flowlinex,flowliney])) # Find where flowline intersects the next ice-front position intersect = flowline.intersection(term2) add = False try: if len(intersect) > 0: ind = np.argmin(abs([intersect[k].x for k in range(0,len(intersect))]-termx1[j])) term2_flowline = [intersect[ind].x,intersect[ind].y] add = True except: try: term2_flowline = [intersect.x,intersect.y] add = True except: pass dflow = distlib.between_pts(termx1[j],termy1[j],term2_flowline[0],term2_flowline[1]) dmid = frac*dflow xmid = np.interp(dmid,[0,dflow],[termx1[j],term2_flowline[0]]) ymid = np.interp(dmid,[0,dflow],[termy1[j],term2_flowline[1]]) if (add == True) and (ymid > ybot) and (ymid < ytop): icefront_x.append(xmid) icefront_y.append(ymid) if i > 0: nonnan = np.where(~(np.isnan(timeseries_x[:,i-1])))[0] front_lasttime = LineString(np.column_stack([timeseries_x[nonnan,i-1],timeseries_y[nonnan,i-1]])) intersect = flowline.intersection(front_lasttime) try: diff = distlib.between_pts(xmid,ymid,intersect.x,intersect.y) except: try: diff = 1000.0 for pt in intersect: newdiff = distlib.between_pts(xmid,ymid,pt.x,pt.y) if newdiff < diff: diff = newdiff if diff == 1000.0: diff = 0 except: diff = 0 if extentpath.contains_point([xmid,ymid]): sign = -1 else: sign = 1 advance.append(sign*diff) else: advance.append(0) icefront_x.append(xbot) icefront_y.append(ybot) if i > 0: if extentpath.contains_point([xbot,ybot]) or (xbot < xbot_old): sign = -1 else: sign = 1 advance.append(sign*distlib.between_pts(xbot,ybot,xbot_old,ybot_old)) else: advance.append(0) # Try sorting icefront to get rid of potential tangles icefront_x_old = np.asarray(icefront_x) icefront_y_old = np.asarray(icefront_y) advance_old = np.asarray(advance) icefront_x = np.zeros_like(icefront_x_old) icefront_y = np.zeros_like(icefront_y_old) advance = np.zeros_like(advance_old) icefront_x[0] = icefront_x_old[0] icefront_y[0] = icefront_y_old[0] advance[0] = advance_old[0] ind = range(1,len(icefront_x_old)) for k in range(1,len(icefront_x_old)): mindist = 10000. for j in range(0,len(ind)): dist = distlib.between_pts(icefront_x[k-1],icefront_y[k-1],icefront_x_old[ind[j]],icefront_y_old[ind[j]]) if dist < mindist: mindist = dist minind = ind[j] icefront_x[k] = icefront_x_old[minind] icefront_y[k] = icefront_y_old[minind] advance[k] = advance_old[minind] ind.remove(minind) # Save icefront in timeseries timeseries_x[0:len(icefront_x),i] = icefront_x timeseries_y[0:len(icefront_y),i] = icefront_y timeseries_dist[0:len(icefront_x),i] = distlib.transect(icefront_x,icefront_y) timeseries_advance[0:len(icefront_x),i] = advance # Now create mesh extent and BC numbers using the interpolated ice front boundterminus = np.ones(len(icefront_x))*2.0 ind1 = np.where((xextent > xbot) & (abs(yextent - ybot) < 1.0e3))[0][0] ind2 = np.where((xextent > xtop) & (abs(yextent - ytop) < 1.0e3))[0][-1] extent_x = np.r_[xextent[0:ind1],np.flipud(icefront_x),xextent[ind2+1:]] extent_y = np.r_[yextent[0:ind1],np.flipud(icefront_y),yextent[ind2+1:]] bound = np.r_[bound_extent[0:ind1],boundterminus,bound_extent[ind2+1:]] xextents[0:len(extent_x),i] = extent_x yextents[0:len(extent_x),i] = extent_y bounds[0:len(extent_x),i] = bound xtop_old = float(xtop) ytop_old = float(ytop) xbot_old = float(xbot) ybot_old = float(ybot) return time, xextents, yextents, bounds, timeseries_x, timeseries_y, timeseries_advance
def load_extent(glacier,time,nofront_shapefile='glacier_extent_nofront'): ''' extent = load_extent(glacier,time) Find the glacier extent that is closest to "time". Inputs: glacier: glacier name time: time (fractional year) when we want the glacier extent Outputs: xextent,yextent: 1-D arrays of x and y coordinates that define glacier extent for that date ''' # Glacier extent with no ice front extent = meshlib.shp_to_xy(os.path.join(os.getenv("DATA_HOME"),"ShapeFiles/Glaciers/3D/"+glacier+"/"+nofront_shapefile)) if extent[1,1] > extent[0,1]: extent = np.flipud(extent) xextent = extent[:,0] yextent = extent[:,1] bound = extent[:,2] dold = distlib.transect(xextent,yextent) dnew = np.arange(0,dold[-1],20.0) xextent = np.interp(dnew,dold,xextent) yextent = np.interp(dnew,dold,yextent) f = scipy.interpolate.interp1d(dold,bound,kind='nearest') bound = f(dnew) # Terminus coordinates xterminus,yterminus,time_terminus = icefrontlib.near_time(time,glacier) if yterminus[-1] > yterminus[0]: xterminus = np.flipud(xterminus) yterminus = np.flipud(yterminus) glacierperimeter = Path(extent[:,0:2]) ind = glacierperimeter.contains_points(np.column_stack([xterminus,yterminus])) xterminus = xterminus[ind] yterminus = yterminus[ind] boundterminus = np.ones(len(xterminus))*2.0 ind1 = np.argmin((xterminus[0]-xextent)**2+(yterminus[0]-yextent)**2) ind2 = np.argmin((xterminus[-1]-xextent)**2+(yterminus[-1]-yextent)**2) if ind2 > ind1: if yextent[ind2] < yextent[ind1]: xextent = np.r_[np.delete(xextent[0:ind2],range(ind1+1,ind2)),np.flipud(xterminus),xextent[ind2+1:]] yextent = np.r_[np.delete(yextent[0:ind2],range(ind1+1,ind2)),np.flipud(yterminus),yextent[ind2+1:]] bound = np.r_[np.delete(bound[0:ind2],range(ind1+1,ind2)),boundterminus,bound[ind2+1:]] else: xextent = np.r_[np.delete(xextent[0:ind2],range(ind1+1,ind2)),xterminus,xextent[ind2+1:]] yextent = np.r_[np.delete(yextent[0:ind2],range(ind1+1,ind2)),yterminus,yextent[ind2+1:]] bound = np.r_[np.delete(bound[0:ind2],range(ind1+1,ind2)),boundterminus,bound[ind2+1:]] else: if yextent[ind2] < yextent[ind1]: xextent = np.r_[np.delete(xextent[0:ind1],range(ind2+1,ind1)),np.flipud(xterminus),xextent[ind1+1:]] yextent = np.r_[np.delete(yextent[0:ind1],range(ind2+1,ind1)),np.flipud(yterminus),yextent[ind1+1:]] bound = np.r_[np.delete(bound[0:ind1],range(ind2+1,ind1)),np.flipud(boundterminus),bound[ind1+1:]] else: xextent = np.r_[np.delete(xextent[0:ind1],range(ind2+1,ind1)),xterminus,xextent[ind1+1:]] yextent = np.r_[np.delete(yextent[0:ind1],range(ind2+1,ind1)),yterminus,yextent[ind1+1:]] bound = np.r_[np.delete(bound[0:ind1],range(ind2+1,ind1)),boundterminus,bound[ind1+1:]] return np.column_stack([xextent,yextent,bound])
sortind = (np.argsort(cut_cresis[:, 1])) cut_cresis = cut_cresis[sortind, :] other = np.row_stack([cresis_all[0:ind1, :], cresis_all[ind2:-1, :]]) else: cut_cresis = cresis_all[ind2:ind1, :] sortind = (np.argsort(cut_cresis[:, 1])) cut_cresis = cut_cresis[sortind, :] other = np.row_stack([cresis_all[0:ind2, :], cresis_all[ind1:-1, :]]) # Distances along transect xtemp = np.append(cut_cresis[:, 0], [addons[j][0], addons[j][2]]) ytemp = np.append(cut_cresis[:, 1], [addons[j][1], addons[j][3]]) sortind = ((np.argsort(ytemp))) xtemp = xtemp[sortind] ytemp = ytemp[sortind] dtemp = distlib.transect(xtemp, ytemp) dists = dtemp[1:-1] # Get morlighem bed cut_dMor = np.linspace(0, dtemp[-1], dtemp[-1] / 150.0) cut_xMor = np.interp(cut_dMor, dtemp, xtemp) cut_yMor = np.interp(cut_dMor, dtemp, ytemp) cut_zMor = bedlib.morlighem_pts(cut_xMor, cut_yMor, glacier, 'geoid') cut_cresis_grid = bedlib.cresis_grid_pts(cut_xMor, cut_yMor, glacier, 'geoid') del xtemp, ytemp, dtemp # Get 2001 Cresis point mindist = 100.0 for i in range(0, len(cut_cresis)): pdist = np.min(
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],:] vy=vy[indices[0],:] divx=divx[indices[0],:]
def fluxbox_geometry(glacier, fluxgate_filename): ''' Find the geometry of the fluxbox by combining the shapefiles for the fluxgates and for the glacier extent. ''' # 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_in_sf = shapefile.Reader(DIR + fluxgate_filename + "_in") gate_out_sf = shapefile.Reader(DIR + fluxgate_filename + "_out") # Glacier extent shapefile glacier_extent = masklib.load_points(glacier) #glacier_extent = meshlib..shp_to_xy(os.path.join(os.getenv("DATA_HOME"), # "ShapeFiles/Glaciers/3D/"+glacier+"/glacier_extent_normal")) #if glacier == 'Helheim': # glacier_hole1 = meshlib..shp_to_xy(os.path.join(os.getenv("DATA_HOME"), # "ShapeFiles/Glaciers/3D/Helheim/glacier_hole1")) # glacier_hole2 = meshlib..shp_to_xy(os.path.join(os.getenv("DATA_HOME"), # "ShapeFiles/Glaciers/3D/Helheim/glacier_hole2")) # glacier_extent = np.row_stack([glacier_extent,glacier_hole1,glacier_hole2]) # Get end points for flux gates gate_in_pts = np.array(gate_in_sf.shapes()[0].points) if gate_in_pts[-1, 1] < gate_in_pts[0, 1]: gate_in_pts = np.flipud(gate_in_pts) gate_out_pts = np.array(gate_out_sf.shapes()[0].points) if gate_out_pts[-1, 1] < gate_out_pts[0, 1]: gate_out_pts = np.flipud(gate_out_pts) # Calculate length of flux gates (i.e., the "width" of glacier) L_in = distlib.transect(gate_in_pts[:, 0], gate_in_pts[:, 1]) L_out = distlib.transect(gate_out_pts[:, 0], gate_out_pts[:, 1]) dl = 50. # Get coordinates of points along upstream flux gate l_in = np.linspace(0, L_in[-1], np.ceil(L_in[-1] / dl) + 1) dl_in = l_in[1] - l_in[0] l_in = l_in[0:-1] + dl_in / 2 x_in = np.interp(l_in, L_in, gate_in_pts[:, 0]) y_in = np.interp(l_in, L_in, gate_in_pts[:, 1]) # Get coordinates of points along downstream flux gate l_out = np.linspace(0, L_out[-1], np.ceil(L_out[-1] / dl) + 1) dl_out = l_out[1] - l_out[0] l_out = l_out[0:-1] + dl_out / 2 x_out = np.interp(l_out, L_out, gate_out_pts[:, 0]) y_out = np.interp(l_out, L_out, gate_out_pts[:, 1]) gate_in_pts = np.column_stack([x_in, y_in]) gate_out_pts = np.column_stack([x_out, y_out]) del l_out, l_in, dl_in, dl_out, x_in, x_out, y_in, y_out # Find glacier geometry (i.e., points in glacier extent) that lie between the flux gates, # so we can calculate glacier area. fluxbox_x = [] # boundary points for area between flux gates fluxbox_x.append(gate_in_pts[:, 0].T.tolist()) fluxbox_y = [] fluxbox_y.append(gate_in_pts[:, 1].T.tolist()) for i in [0, -1]: ind_in = np.argmin((gate_in_pts[i, 0] - glacier_extent[:, 0])**2 + (gate_in_pts[i, -1] - glacier_extent[:, 1])** 2) # get closest index ind_out = np.argmin((gate_out_pts[i, 0] - glacier_extent[:, 0])**2 + (gate_out_pts[i, -1] - glacier_extent[:, 1])** 2) # get closest index # Check to make sure we didn't grab a point outside the flux box # The x-value of glacier extent near the upstream flux gate needs to be greater than the # x-value of the flux gate to be in the box. Check to see if it's smaller and if so correct it. if gate_in_pts[i, 0] > glacier_extent[ind_in, 0]: if gate_in_pts[i, 0] < glacier_extent[ind_in - 1, 0]: ind_in = ind_in - 1 else: ind_in = ind_in + 1 # The opposite is true for the downstream gate. if gate_out_pts[i, 0] < glacier_extent[ind_out, 0]: if gate_out_pts[i, 0] > glacier_extent[ind_out - 1, 0]: ind_out = ind_out - 1 else: ind_out = ind_out + 1 # Add points from glacier extent to flux box if ind_in < ind_out: fluxbox_x.append(glacier_extent[ind_in:ind_out + 1, 0].tolist()) fluxbox_y.append(glacier_extent[ind_in:ind_out + 1, 1].tolist()) else: fluxbox_x.append(glacier_extent[ind_out:ind_in + 1, 0].tolist()) fluxbox_y.append(glacier_extent[ind_out:ind_in + 1, 1].tolist()) fluxbox_x.append(gate_out_pts[:, 0].T.tolist()) fluxbox_y.append(gate_out_pts[:, 1].T.tolist()) fluxbox_x = sum(fluxbox_x, []) fluxbox_y = sum(fluxbox_y, []) fluxbox_x, fluxbox_y = coordlib.sort_xy(fluxbox_x, fluxbox_y) fluxbox_x.append(fluxbox_x[0]) fluxbox_y.append(fluxbox_y[0]) return fluxbox_x, fluxbox_y
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]
surf = np.zeros_like(xdata) bed = np.zeros_like(xdata) height = np.zeros_like(xdata) ndata = np.zeros_like(tempdata[:, 0]) elevation = np.zeros_like(tempdata[:, 0]) for i in range(0, len(xdata)): colinds = np.array(np.where(tempdata[:, 0] == xdata[i])) surf[i] = np.max(tempdata[colinds, 2]) # Surface elevation bed[i] = np.min(tempdata[colinds, 2]) # Bed elevation height[i] = surf[i] - bed[i] #height elevation[colinds] = tempdata[colinds, 2] ndata[colinds] = (tempdata[colinds, 2] - bed[i]) / height[i] #normalized value # Compute distance along Kristin's temperature profile ddata = distlib.transect(tempdata[:, 0], tempdata[:, 1]) # Compute distance between our flowline and Kristin's, so that we can adjust # the distance in Kristin's temperature profile so that it aligns dist1 = np.sqrt((xdata[0] - flowline[0, 1])**2 + (ydata[0] - flowline[0, 2])**2) dist2 = np.sqrt((xdata[1] - flowline[0, 1])**2 + (ydata[1] - flowline[0, 2])**2) ddata = ddata - ddata[200] * (dist1 / (dist1 + dist2)) + flowline[0, 0] # Write out depths for flowline so that we can use those depths for interpolation pts = np.zeros([len(flowline[:, 0]) * layers * 2, 3]) for i in range(0, len(flowline[:, 0])): pts[layers * 2 * i:layers * 2 * (i + 1), 0] = flowline[i, 0] pts[layers * 2 * i:layers * 2 * (i + 1), 1] = np.linspace(0, 1, layers * 2) pts[layers * 2 * i:layers * 2 * (i + 1),