def site_filter_extent(extent, srs=geolib.wgs_srs, pad=None): """ Filter available sites for a given lat/lon extent """ sites = get_all_lonlat() sites_srs = geolib.wgs_srs if not srs.IsSame(sites_srs): print("Converting SNOTEL lat/lon to input ds projection") #This returns (x,y,z) coordinate arrays sites_proj = np.array( geolib.cT_helper(sites[:, 1], sites[:, 2], 0, sites_srs, srs)).T #Replace the original lon and lat coordinates with projected x and y sites[:, 1:3] = sites_proj[:, 0:2] #print(extent) #print(sites) if pad is not None: print("Padding original extent by: %s km" % pad) #Convert to meters pad *= 1000. extent = geolib.pad_extent(extent, width=pad) #print(extent) valid_idx = ((sites[:, 1] > extent[0]) & (sites[:, 1] < extent[2]) & (sites[:, 2] > extent[1]) & (sites[:, 2] < extent[3])) valid_sites = sites[valid_idx] #Only return site codes, not lat/lon #valid_sites = valid_sites[:,0].astype(int) if valid_sites.size == 0: valid_sites = None return valid_sites
def get_raster_idx(x_vect, y_vect, pt_srs, ras_ds, max_slope=20): """Get raster index corresponding to the set of X,Y locations """ #Convert input xy coordinates to raster coordinates mX_fltr, mY_fltr, mZ = geolib.cT_helper(x_vect, y_vect, 0, pt_srs, geolib.get_ds_srs(ras_ds)) pX_fltr, pY_fltr = geolib.mapToPixel(mX_fltr, mY_fltr, ras_ds.GetGeoTransform()) pX_fltr = np.atleast_1d(pX_fltr) pY_fltr = np.atleast_1d(pY_fltr) #Sample raster #This returns median and mad for ICESat footprint samp = geolib.sample(ras_ds, mX_fltr, mY_fltr, pad=pad) samp_idx = ~(np.ma.getmaskarray(samp[:,0])) npts = samp_idx.nonzero()[0].size if False: print("Applying slope filter, masking points with slope > %0.1f" % max_slope) slope_ds = geolib.gdaldem_mem_ds(ras_ds, processing='slope', returnma=False) slope_samp = geolib.sample(slope_ds, mX_fltr, mY_fltr, pad=pad) slope_samp_idx = (slope_samp[:,0] <= max_slope).data samp_idx = np.logical_and(slope_samp_idx, samp_idx) return samp, samp_idx, npts, pX_fltr, pY_fltr
def shp_overlay(ax, ds, shp_fn, gt=None, color='darkgreen'): from osgeo import ogr from pygeotools.lib import geolib #ogr2ogr -f "ESRI Shapefile" output.shp input.shp -clipsrc xmin ymin xmax ymax shp_ds = ogr.Open(shp_fn) lyr = shp_ds.GetLayer() lyr_srs = lyr.GetSpatialRef() lyr.ResetReading() nfeat = lyr.GetFeatureCount() #Note: this is inefficient for large numbers of features #Should produce collections of points or lines, then have single plot call for n, feat in enumerate(lyr): geom = feat.GetGeometryRef() geom_type = geom.GetGeometryType() #Points if geom_type == 1: mX, mY, z = geom.GetPoint() attr = {'marker':'o', 'markersize':5, 'linestyle':'None'} #Line elif geom_type == 2: l, mX, mY = geolib.line2pts(geom) z = 0 #attr = {'marker':None, 'linestyle':'-', 'linewidth':0.5, 'alpha':0.8} attr = {'marker':None, 'linestyle':'-', 'linewidth':1.0, 'alpha':0.8} #attr = {'marker':'.', 'markersize':0.5, 'linestyle':'None'} #Polygon, placeholder #Note: this should be done with the matplotlib patch functionality #http://matplotlib.org/users/path_tutorial.html elif geom_type == 3: print("Polygon support not yet implemented") #ogr2ogr -nlt LINESTRING out.shp in.shp l, mX, mY = geolib.line2pts(geom) z = 0 attr = {'marker':None, 'linestyle':'-', 'facecolor':'w'} ds_srs = geolib.get_ds_srs(ds) if gt is None: gt = ds.GetGeoTransform() if not lyr_srs.IsSame(ds_srs): mX, mY, z = geolib.cT_helper(mX, mY, z, lyr_srs, ds_srs) #ds_extent = geolib.ds_extent(ds) ds_extent = geolib.ds_geom_extent(ds) mX = np.ma.array(mX) mY = np.ma.array(mY) mX[mX < ds_extent[0]] = np.ma.masked mX[mX > ds_extent[2]] = np.ma.masked mY[mY < ds_extent[1]] = np.ma.masked mY[mY > ds_extent[3]] = np.ma.masked mask = np.ma.getmaskarray(mY) | np.ma.getmaskarray(mX) mX = mX[~mask] mY = mY[~mask] if mX.count() > 0: ax.set_autoscale_on(False) if geom_type == 1: pX, pY = geolib.mapToPixel(np.array(mX), np.array(mY), gt) ax.plot(pX, pY, color=color, **attr) else: l = np.ma.array(l) l = l[~mask] lmed = np.ma.median(np.diff(l)) lbreaks = (np.diff(l) > lmed*2).nonzero()[0] if lbreaks.size: a = 0 lbreaks = list(lbreaks) lbreaks.append(l.size) for b in lbreaks: mmX = mX[a:b+1] mmY = mY[a:b+1] a = b+1 #import ipdb; ipdb.set_trace() #pX, pY = geolib.mapToPixel(np.array(mX), np.array(mY), gt) pX, pY = geolib.mapToPixel(mmX, mmY, gt) print(n, np.diff(pX).max(), np.diff(pY).max()) #ax.plot(pX, pY, color='LimeGreen', **attr) #ax.plot(pX, pY, color='LimeGreen', alpha=0.5, **attr) #ax.plot(pX, pY, color='w', alpha=0.5, **attr) ax.plot(pX, pY, color=color, **attr) else: pX, pY = geolib.mapToPixel(np.array(mX), np.array(mY), gt) ax.plot(pX, pY, color=color, **attr)
aea_srs = geolib.conus_aea_srs title = "CONUS Glacier Mass Balance (1950s-1980s to 2015)" #title = "CONUS Glacier Mass Balance (1950s-1980s to 2007-2009)" #title = "CONUS Glacier Mass Balance (2007-2009 to 2015)" #title = "CONUS Glacier Mass Balance (2000 to 2015)" #title = "CONUS Glacier Mass Balance (1950s-1980s to 2000)" sf = 16 elif site == 'hma': aea_srs = geolib.hma_aea_srs #title = "HMA Glacier Mass Balance (1970s to 2015)" #title = "HMA Glacier Mass Balance (1970s to 2000)" title = "HMA Glacier Mass Balance (2000 to 2015)" sf = 2 #Compute lat, lon lon, lat, dummy = geolib.cT_helper(a['x'],a['y'],0,aea_srs,geolib.wgs_srs) a = recfunctions.append_fields(a, 'lon', lon, dtypes=None, usemask=False) a = recfunctions.append_fields(a, 'lat', lat, dtypes=None, usemask=False) #utm_srs = osr.SpatialReference() #utm_srs.ImportFromEPSG(32610) #x_utm, y_utm, dummy = geolib.cT_helper(a['x'],a['y'],0,aea_srs,utm_srs) vmin, vmax = get_equal_vmin_vmax(a['mb_mwea']) #vmin, vmax = (-0.7, 0.7) vmin, vmax = (-1.0, 1.0) if True: #f, ax = plt.subplots(figsize=(10,8)) f, ax = plt.subplots() ax = mapplot(a, field='mb_mwea', srs=aea_srs, sf=sf, ax=ax, clim=(vmin, vmax))
x_fltr = glas_pts_fltr[:,xcol] y_fltr = glas_pts_fltr[:,ycol] z_fltr = glas_pts_fltr[:,zcol] dem_mask_fn = os.path.splitext(dem_fn)[0]+'_ref.tif' if os.path.exists(dem_mask_fn): print("Loading Masked DEM: %s" % dem_mask_fn) dem_mask_ds = gdal.Open(dem_mask_fn) dem_mask = iolib.ds_getma(dem_mask_ds) else: dem_mask_ds = dem_ds dem_mask = dem_ma #Convert input xy coordinates to raster coordinates mX_fltr, mY_fltr, mZ = geolib.cT_helper(x_fltr, y_fltr, 0, pt_srs, geolib.get_ds_srs(dem_mask_ds)) pX_fltr, pY_fltr = geolib.mapToPixel(mX_fltr, mY_fltr, dem_mask_ds.GetGeoTransform()) pX_fltr = np.atleast_1d(pX_fltr) pY_fltr = np.atleast_1d(pY_fltr) #Sample raster #This returns median and mad for ICESat footprint samp = geolib.sample(dem_mask_ds, mX_fltr, mY_fltr, pad=pad) samp_idx = ~(np.ma.getmaskarray(samp[:,0])) npts = samp_idx.nonzero()[0].size if npts < min_pts: print("Not enough points after sampling valud pixels, post bareground mask (%i < %i)" % (npts, min_pts)) continue if True: print("Applying slope filter, masking points with slope > %0.1f" % max_slope)
#Clustering, gridding import numpy as np from pygeotools.lib import timelib, geolib, iolib from osgeo import osr glas_csv_fn = 'GLAH14_chad_refdemfilt.csv' srtm_fn = 'chad_nasadem_hgt_merge_hgt_adj_proj_hs_az315.tif' srtm_ds = iolib.fn_getds(srtm_fn) # dt_ordinal, dt_YYYYMMDD, lat, lon, z_WGS84, z_refdem_med_WGS84, z_refdem_nmad glas_pts = np.loadtxt(glas_csv_fn, delimiter=',', skiprows=1, dtype=None) srs = osr.SpatialReference() srs.ImportFromEPSG(32633) x, y, z = geolib.cT_helper(glas_pts[:, 3], glas_pts[:, 2], glas_pts[:, 4], geolib.wgs_srs, srs) #pt_array = glas_pts[:,[3,2,4,0]] pt_array = np.array([x, y, z, glas_pts[:, 0]]).T #Cluster dt_thresh = 16.0 d = np.diff(pt_array[:, 3]) b = np.nonzero(d > dt_thresh)[0] + 1 b = np.hstack((0, b, d.shape[0])) f_list = [] dt_list = [] for i in range(len(b) - 1): f = pt_array[b[i]:b[i + 1]] min_dt = timelib.o2dt(f[:, 3].min()) max_dt = timelib.o2dt(f[:, 3].max())
np.savetxt(out_csv_valsurf_fn, glas_pts_fltr_valsurf, header=hdr_out, fmt=fmt_out, delimiter=',', comments='') if os.path.exists(dem_mask_fn): print("Writing out %i ICESat-GLAS shots for co-registration" % glas_pts_fltr_coreg.shape[0]) out_csv_fn_coreg = os.path.splitext(out_csv_fn)[0]+'_ref.csv' #lat,lon,elev_ground for pc_align out_csv_fn_coreg_asp = os.path.splitext(out_csv_fn)[0]+'_ref_asp.csv' #Could add DEM samp columns here np.savetxt(out_csv_fn_coreg, glas_pts_fltr_coreg, header=hdr_out, fmt=fmt_out, delimiter=',', comments='') np.savetxt(out_csv_fn_coreg_asp, glas_pts_fltr_coreg_asp, fmt='%0.6f, %0.6f, %0.2f', delimiter=',') # For plotting the qfilt ICESat-GLAS used for co-reg x_fltr_mask_coreg = glas_pts_fltr_coreg[:,xcol] y_fltr_mask_coreg = glas_pts_fltr_coreg[:,ycol] z_fltr_mask_coreg = glas_pts_fltr_coreg[:,zcol] mX_fltr_mask_coreg, mY_fltr_mask_coreg, mZ_coreg = geolib.cT_helper(x_fltr_mask_coreg, y_fltr_mask_coreg, 0, pt_srs, geolib.get_ds_srs(dem_mask_ds)) pX_fltr_mask_coreg, pY_fltr_mask_coreg = geolib.mapToPixel(mX_fltr_mask_coreg, mY_fltr_mask_coreg, dem_mask_ds.GetGeoTransform()) pX_fltr_mask_coreg = np.atleast_1d(pX_fltr_mask_coreg) pY_fltr_mask_coreg = np.atleast_1d(pY_fltr_mask_coreg) # For plotting the qfilt ICESat-GLAS used for examining all valid surfaces x_fltr_mask_valsurf = glas_pts_fltr_valsurf[:,xcol] y_fltr_mask_valsurf = glas_pts_fltr_valsurf[:,ycol] z_fltr_mask_valsurf = glas_pts_fltr_valsurf[:,zcol] mX_fltr_mask_valsurf, mY_fltr_mask_valsurf, mZ_valsurf = geolib.cT_helper(x_fltr_mask_valsurf, y_fltr_mask_valsurf, 0, pt_srs, geolib.get_ds_srs(dem_chmmask_ds)) pX_fltr_mask_valsurf, pY_fltr_mask_valsurf = geolib.mapToPixel(mX_fltr_mask_valsurf, mY_fltr_mask_valsurf, dem_chmmask_ds.GetGeoTransform()) pX_fltr_mask_valsurf = np.atleast_1d(pX_fltr_mask_valsurf) pY_fltr_mask_valsurf = np.atleast_1d(pY_fltr_mask_valsurf) # Get the elev dif b/w GLAS and DEM dz = z_fltr_mask_coreg - coreg_samp[coreg_samp_idx,0]
if utmn > 4400000: utmn /= 10. if utme > 4400000: utme /= 10. #These are sometimes swapped if utme > utmn: utmn, utme = utme, utmn #Determine UTM zone if int(str(utme)[0]) == 2: utmzone = 13 elif int(str(utme)[0]) == 7: utmzone = 12 #Transform coordinates to UTM 13N print("Transformng coordinates to UTM 13N") utme, utmn, dummy = geolib.cT_helper(utme, utmn, 0, utm12n_srs, utm13n_srs) #Some points are in lat/lon (39.01053, 108.187) elif int(str(utme)[0]) == 3: print("Transformng coordinates to UTM 13N") utme, utmn, dummy = geolib.cT_helper(utmn, utme, 0, geolib.wgs_srs, utm13n_srs) else: sys.exit(utme) #Extract depth depth = None if ws['F6'].value is not None and ws['F6'].value[0].isdigit(): depth = float(ws['F6'].value.split('-')[-1].split()[0].split('cm')[0]) elif ws['B10'].value is not None and ws['B10'].value[0].isdigit(): depth = float(ws['B10'].value) if depth is not None: depth /= 100.