cmap='gray',
           vmin=clim[0],
           vmax=clim[1],
           s=36)
ax.set_xlabel('Pit snow depth (m)')
ax.set_ylabel('Stereo2SWE snow depth (m)')
ax.plot([0, 3], [0, 3], color='r', linewidth=0.5)
ax.set_xlim(0, max_depth)
ax.set_ylim(0, max_depth)
fig_fn = 'snowex_gm_snowdepth_scatter.pdf'
f.savefig(fig_fn, dpi=300, bbox_inches='tight')

#Snow depth histogram of signed diff
f, ax = plt.subplots()
ax.hist(depth_diff, bins=64, range=(-max_depth, max_depth), color='k')
malib.print_stats(depth_diff)
ax.set_xlabel('Snow Depth Diff., Pit - DEM (m)')
ax.set_ylabel('Count')
fig_fn = 'snowex_gm_snowdepth_diff_hist.pdf'
f.savefig(fig_fn, dpi=300, bbox_inches='tight')

#Map plot of snow depth
f, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_facecolor('k')
ax.imshow(hs, cmap='gray')
#clim = malib.calcperc(depth, (2,98))
clim = (0, 2)
im = ax.imshow(snowdepth, cmap='inferno', clim=clim, alpha=0.7)
ax.set_ylim(dem.shape[0], 0)
ax.set_xlim(0, dem.shape[1])
                     xy_srs=xy_srs,
                     pad='glas',
                     count=True)
samp_idx = ~(np.ma.getmaskarray(samp[:, 0]))
nsamp = samp_idx.nonzero()[0].size

if nsamp == 0:
    sys.exit("No valid samples")
else:
    pts_mask = np.ma.hstack([
        pts[samp_idx], samp[samp_idx],
        (pts[samp_idx, zcol] - samp[samp_idx, 0])[:, np.newaxis]
    ])

    print("Sample difference (raster - point) statistics:")
    malib.print_stats(pts_mask[:, -1])
    """
    #Update header
    out_hdr_str = None
    if hdr is not None:
        out_hdr = hdr + ['samp_med','samp_nmad','samp_count']
        out_hdr_str = ', '.join(fieldnames)

    #Format for new cols
    #fmt = ['%0.2f', '%0.2f', '%i']
    #fmt = None
    """

    out_pt_fn = os.path.splitext(r_fn)[0] + '_' + os.path.splitext(
        os.path.split(pt_fn)[-1])[0] + '_sample.csv'
    print("\nWriting out %i points with valid samples:\n%s\n" %
Esempio n. 3
0
def main():
    parser = getparser()
    args = parser.parse_args()

    dem_fn = args.dem_fn

    # Write out because they will be used to mask CHM
    writeall = True

    # Auto compute min TOA with gaussian mixture model
    compute_min_toa = True

    #Basename for output files
    out_fn_base = os.path.splitext(dem_fn)[0]

    #Need some checks on these
    param = args.filt_param
    if param is not None and len(param) == 1:
        param = param[0]
    # Get original DEM
    dem = iolib.fn_getma(dem_fn)

    print("\nLoading input DEM into masked array")
    dem_ds = iolib.fn_getds(dem_fn)

    toa_mask = None
    toa_tri_mask = None  # probably not used by itself; done as part of toa_mask
    rough_mask = None
    slope_mask = None
    mask_list = [toa_tri_mask, toa_mask, rough_mask, slope_mask]

    if args.filtdz:
        print(
            "\nFilter with dz from ref DEM to remove cloud returns and blunders (shadows)..."
        )
        print("Reference DEM: %s" % os.path.split(param[0])[1])
        print("Absolute dz (+/-): %s \n" % param[2])
        #May need to cast input ma as float32 so np.nan filling works
        dem = dem.astype(np.float32)

        #Difference filter, need to specify ref_fn and range
        #Could let the user compute their own dz, then just run a standard range or absrange filter
        ref_fn = param[0]
        ref_ds = warplib.memwarp_multi_fn([
            ref_fn,
        ],
                                          res=dem_ds,
                                          extent=dem_ds,
                                          t_srs=dem_ds)[0]
        ref = iolib.ds_getma(ref_ds)
        param = map(float, param[1:])

        # A dem that has been masked based on the dz filter
        dem = filtlib.dz_fltr_ma(dem, ref, rangelim=param)

        if writeall:
            out_fn = os.path.splitext(dem_fn)[0] + '_dzfilt.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(dem, out_fn, src_ds=dem_ds, ndv=args.ndv)

    #Initialize a control mask that we'll update
    #True (1) represents "valid" unmasked pixel, False (0) represents "invalid" pixel to be masked
    controlmask = ~(np.ma.getmaskarray(dem))

    # DEM masking: Each block returns a masked output (not a mask)
    #    TOA: mask dark and/or smooth areas (shadows and/or water)
    #    Roughness
    #    Slope

    if args.toamask or args.toatrimask:

        print("\nCompute TOA from ortho...\n")
        toa_fn = get_toa_fn(dem_fn)
        print("\nWarp TOA to DEM...\n")
        toa_ds = warplib.memwarp_multi_fn([
            toa_fn,
        ],
                                          res=dem_ds,
                                          extent=dem_ds,
                                          t_srs=dem_ds)[0]

        if args.toamask:

            if compute_min_toa:

                # Compute a good min TOA value
                m, s = get_min_gaus(toa_fn, 50, 4)
                min_toa = m + s
                min_toa = m
            else:
                min_toa = args.min_toa

            with open(os.path.join(os.path.split(toa_fn)[0], "min_toa.txt"),
                      "w") as text_file:
                text_file.write(os.path.basename(__file__))
                text_file.write(
                    "\nMinimum TOA used for mask:\n{0}".format(min_toa))

            # Should mask dark areas and dilate
            toa_mask = get_toa_mask(toa_ds, min_toa)

            #Dilate the mask
            if args.dilate_toa is not None:
                niter = args.dilate_toa
                print("Dilating TOA mask with %i iterations" % niter)
                from scipy import ndimage
                toa_mask = ~(ndimage.morphology.binary_dilation(
                    ~toa_mask, iterations=niter))

            controlmask = np.logical_and(toa_mask, controlmask)

            # Mask islands here
            controlmask = malib.mask_islands(controlmask, 5)

            if writeall:
                out_fn = out_fn_base + '_toamask.tif'
                print("Writing out %s\n" % out_fn)
                iolib.writeGTiff(toa_mask, out_fn, src_ds=dem_ds)

        if args.toatrimask:
            # Should mask smooth areas (measures local variance)
            toa_tri_mask = get_tri_mask(toa_ds, args.min_toatri)
            controlmask = np.logical_and(toa_tri_mask, controlmask)

            if writeall:
                out_fn = out_fn_base + '_toatrimask.tif'
                print("Writing out %s\n" % out_fn)
                iolib.writeGTiff(toa_tri_mask, out_fn, src_ds=dem_ds)

    if args.slopemask:
        slope_mask = get_slope_mask(dem_ds, args.max_slope)
        controlmask = np.logical_and(slope_mask, controlmask)
        if writeall:
            out_fn = out_fn_base + '_slopemask.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(slope_mask, out_fn, src_ds=dem_ds)

    # CHM mask will be a subset of the Control mask; slope_mask, toa_mask, toa_tri_mask
    chmmask = controlmask
    print("Generating final CHM mask to apply later")
    out_fn = out_fn_base + '_chmmask.tif'
    print("Writing out %s\n" % out_fn)
    iolib.writeGTiff(chmmask, out_fn, src_ds=dem_ds)

    if args.roughmask:
        rough_mask = get_rough_mask(dem_ds, args.max_rough)
        controlmask = np.logical_and(rough_mask, controlmask)
        if writeall:
            out_fn = out_fn_base + '_roughmask.tif'
            print("Writing out %s\n" % out_fn)
            iolib.writeGTiff(rough_mask, out_fn, src_ds=dem_ds)

    print(
        "Generating final mask to use for reference surfaces, and applying to input DEM"
    )
    #Now invert to use to create final masked array
    controlmask = ~controlmask

    #Dilate the mask
    if args.dilate_con is not None:
        niter = args.dilate_con
        print("Dilating control mask with %i iterations" % niter)
        from scipy import ndimage
        controlmask = ~(ndimage.morphology.binary_dilation(~controlmask,
                                                           iterations=niter))

    #Apply mask to original DEM - use these surfaces for co-registration
    newdem = np.ma.array(dem, mask=controlmask)

    if True:
        print("\nStats of valid DEM with maskes applied:")
        valid_stats = malib.print_stats(newdem)
        valid_stats_med = valid_stats[5]

    print("\nWriting DEM control surfaces:")
    dst_fn = os.path.splitext(dem_fn)[0] + '_control.tif'
    print(dst_fn)
    iolib.writeGTiff(newdem, dst_fn, dem_ds)

    return dst_fn
Esempio n. 4
0
def main():
    parser = getparser()
    args = parser.parse_args()

    #This is output ndv, avoid using 0 for differences
    diffndv = -9999

    r1_fn = args.fn1
    r2_fn = args.fn2

    if r1_fn == r2_fn:
        sys.exit('Input filenames are identical')

    fn_list = [r1_fn, r2_fn]

    outdir = args.outdir
    if outdir is None:
        outdir = os.path.dirname(os.path.abspath(r1_fn))

    if not os.path.exists(outdir):
        os.makedirs(outdir)

    outprefix = os.path.splitext(os.path.split(r1_fn)[1])[0]+'_'+os.path.splitext(os.path.split(r2_fn)[1])[0]

    #Compute dz/dt rate if possible, in m/yr
    if args.rate:
        #Extract basename
        #This was a hack to work with timestamp array filenames that have geoid offset applied
        adj = ''
        if '-adj' in r1_fn:
            adj = '-adj' 
        r1_fn_base = re.sub(adj, '', os.path.splitext(r1_fn)[0]) 
        r2_fn_base = re.sub(adj, '', os.path.splitext(r2_fn)[0]) 

        #Attempt to load ordinal timestamp arrays (for mosaics) if present
        """
        import glob
        t1_fn = glob.glob(r1_fn_base+'*_ts*.tif')
        t2_fn = glob.glob(r1_fn_base+'*_ts*.tif')
        t_unit = 'year'
        """
        t1_fn = r1_fn_base+'_ts.tif'
        t2_fn = r2_fn_base+'_ts.tif'
        t_unit = 'day'
        if not os.path.exists(t1_fn) and not os.path.exists(t2_fn):
            #Try to find processed output from r_mosaic index
            #These are decimal years
            t1_fn = r1_fn_base+'index_ts.tif'
            t2_fn = r2_fn_base+'index_ts.tif'
            t_unit = 'year'
        print(t1_fn, t2_fn)
        if os.path.exists(t1_fn) and os.path.exists(t2_fn):
            fn_list.extend([t1_fn, t2_fn])
        else:
            #Attempt to extract timestamps from input filenames
            t1 = timelib.fn_getdatetime(r1_fn)
            t2 = timelib.fn_getdatetime(r2_fn)
            if t1 is not None and t2 is not None and t1 != t2:  
                dt = t2 - t1
                year = timedelta(days=365.25)
                t_factor = abs(dt.total_seconds()/year.total_seconds()) 
                print("Time differences is %s, dh/%0.3f" % (dt, t_factor))
            else:
                print("Unable to extract timestamps for input images")
                args.rate = False


    print("Warping rasters to same res/extent/proj")
    #This will check input param for validity, could do beforehand
    ds_list = warplib.memwarp_multi_fn(fn_list, extent=args.te, res=args.tr, t_srs=args.t_srs, r='cubic')
    r1_ds = ds_list[0]
    r2_ds = ds_list[1]

    print("Loading input rasters into masked arrays")
    r1 = iolib.ds_getma(r1_ds, 1)
    r2 = iolib.ds_getma(r2_ds, 1)

    #Compute relative difference 
    print("Computing raster difference")
    diff = r2 - r1

    #Check to make sure inputs actually intersect
    if diff.count() == 0:
        sys.exit("No valid overlap between input rasters")

    if len(fn_list) == 4:
        t1_ds = ds_list[2]
        t2_ds = ds_list[3]
        print("Loading timestamps into masked arrays")
        t1 = iolib.ds_getma(t1_ds)
        t2 = iolib.ds_getma(t2_ds)
        #Compute dt in years 
        t_factor = t2 - t1
        if t_unit == 'day':
            t_factor /= 365.25

    if True:
        print("Raster difference stats:")
        diff_stats = malib.print_stats(diff)
        diff_med = diff_stats[5]

    if True:
        print("Writing raster difference map")
        dst_fn = os.path.join(outdir, outprefix+'_diff.tif')
        print(dst_fn)
        iolib.writeGTiff(diff, dst_fn, r1_ds, ndv=diffndv)
        if args.rate:
            print("Writing rate map")
            dst_fn = os.path.join(outdir, outprefix+'_diff_rate.tif')
            print(dst_fn)
            iolib.writeGTiff(diff/t_factor, dst_fn, r1_ds, ndv=diffndv)
            if len(fn_list) == 4:
                print("Writing time difference map")
                dst_fn = os.path.join(outdir, outprefix+'_diff_dt.tif')
                print(dst_fn)
                iolib.writeGTiff(t_factor, dst_fn, r1_ds, ndv=diffndv)

    if False:
        print("Writing relative raster difference map")
        diff_rel = diff - diff_med
        dst_fn = os.path.join(outdir, outprefix+'_diff_rel.tif')
        print(dst_fn)
        iolib.writeGTiff(diff_rel, dst_fn, r1_ds, ndv=diffndv)

    if False:
        print("Writing out raster2 with median difference removed")
        dst_fn = os.path.splitext(r2_fn)[0]+'_med'+diff_med+'.tif'
        print(dst_fn)
        iolib.writeGTiff(r2 - diff_med, dst_fn, r1_ds, ndv=diffndv)

    if False:
        print("Writing raster difference percentage map (relative to raster1)")
        diff_perc = 100.0*diff/r1
        dst_fn = os.path.join(outdir, outprefix+'_diff_perc.tif')
        print(dst_fn)
        iolib.writeGTiff(diff_perc, dst_fn, r1_ds, ndv=diffndv)
Esempio n. 5
0
#! /usr/bin/env python

from osgeo import gdal

from pygeotools.lib import iolib
from pygeotools.lib import geolib
from pygeotools.lib import malib

def dist(pos1, pos2):
    return np.sqrt((pos1[0] - pos2[0])**2 + (pos1[1] - pos2[1])**2)

pos1 = [595396.48277,5181880.22677]
pos2 = [596168.611,5182875.521]

fn = ('rainierlidar_wgs84_shpclip.tif')
ds = iolib.fn_getds(fn)
dem = iolib.ds_getma(ds)
x, y = geolib.get_xy_grids(ds)

d = dist(pos1, pos2)
grid = np.array([x, y])
b = dist(pos1, grid)
c = dist(pos2, grid)
conv = np.rad2deg(np.arccos((b**2 + c**2 - d**2)/(2*b*c)))
conv_m = np.ma.array(conv, mask=dem.mask)
malib.print_stats(conv_m)
Esempio n. 6
0
def main():
    #This is defualt filter size (pixels) 
    size = 19
    #Compute and print stats before/after
    stats = False 

    #Need to clean up with argparse
    #Accept filter list, filter size as argument

    if len(sys.argv) == 2:
        dem_fn = sys.argv[1]
    elif len(sys.argv) == 3:
        dem_fn = sys.argv[1]
        size = int(sys.argv[2])
    else:
        sys.exit("Usage is %s dem [size]" % sys.argv[0])
   
    print("Loading DEM into masked array")
    dem_ds = iolib.fn_getds(dem_fn)
    dem = iolib.ds_getma(dem_ds, 1)
    #Cast input ma as float32 so np.nan filling works
    #dem = dem.astype(np.float32)

    dem_fltr = dem

    #Should accept arbitrary number of ordered filter operations as cli argument
    #filt_list = ['gauss_fltr_astropy',]
    #for filt in filt_list:
    #    dem_fltr = filtlib.filt(dem_fltr, size=size, kwargs)

    #Percentile filter
    #dem_fltr = filtlib.perc_fltr(dem, perc=(15.865, 84.135))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(2.275, 97.725))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0.135, 99.865))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 99.73))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 95.45))
    #dem_fltr = filtlib.perc_fltr(dem, perc=(0, 68.27))

    #Difference filter, need to specify refdem_fn
    #dem_fltr = filtlib.dz_fltr(dem_fn, refdem_fn, abs_dz_lim=(0,30))

    #Absolute range filter
    #dem_fltr = filtlib.range_fltr(dem_fltr, (15, 9999))

    #Median filter
    #dem_fltr = filtlib.rolling_fltr(dem_fltr, f=np.nanmedian, size=size)
    #dem_fltr = filtlib.median_fltr(dem_fltr, fsize=size, origmask=True)
    #dem_fltr = filtlib.median_fltr_skimage(dem_fltr, radius=4, origmask=True)

    #High pass filter
    #dem_fltr = filtlib.highpass(dem_fltr, size=size)

    #Gaussian filter (default)
    dem_fltr = filtlib.gauss_fltr_astropy(dem_fltr, size=size, origmask=True, fill_interior=False)

    if stats:
        print("Input DEM stats:")
        malib.print_stats(dem)
        print("Filtered DEM stats:")
        malib.print_stats(dem_fltr)
    
    dst_fn = os.path.splitext(dem_fn)[0]+'_filt%ipx.tif' % size
    print("Writing out filtered DEM: %s" % dst_fn)
    #Note: writeGTiff writes dem_fltr.filled()
    iolib.writeGTiff(dem_fltr, dst_fn, dem_ds) 
Esempio n. 7
0
def main():
    parser = getparser()
    args = parser.parse_args()

    #This is output ndv, avoid using 0 for differences
    diffndv = np.nan

    dem1_fn = args.dem1_fn
    dem2_fn = args.dem2_fn

    if dem1_fn == dem2_fn:
        sys.exit('Input filenames are identical')

    fn_list = [dem1_fn, dem2_fn]

    print("Warping DEMs to same res/extent/proj")
    dem1_ds, dem2_ds = warplib.memwarp_multi_fn(fn_list,
                                                extent=args.te,
                                                res=args.tr,
                                                t_srs=args.t_srs)

    print("Loading input DEMs into masked arrays")
    dem1 = iolib.ds_getma(dem1_ds)
    dem2 = iolib.ds_getma(dem2_ds)

    outdir = args.outdir
    if outdir is None:
        outdir = os.path.split(dem1_fn)[0]
    outprefix = os.path.splitext(
        os.path.split(dem1_fn)[1])[0] + '_' + os.path.splitext(
            os.path.split(dem2_fn)[1])[0]

    #Extract basename
    adj = ''
    if '-adj' in dem1_fn:
        adj = '-adj'
    dem1_fn_base = re.sub(adj, '', os.path.splitext(dem1_fn)[0])
    dem2_fn_base = re.sub(adj, '', os.path.splitext(dem2_fn)[0])

    #Check to make sure inputs actually intersect
    #Masked pixels are True
    if not np.any(~dem1.mask * ~dem2.mask):
        sys.exit("No valid overlap between input data")

    #Compute common mask
    print("Generating common mask")
    common_mask = malib.common_mask([dem1, dem2])

    #Compute relative elevation difference with Eulerian approach
    print("Computing elevation difference with Eulerian approach")
    diff_euler = np.ma.array(dem2 - dem1, mask=common_mask)

    #Absolute range filter on the difference
    # removes differences outside of a range that likely arent related to canopy heights
    diff_euler = range_fltr(diff_euler, (-3, 30))

    if True:
        print("Eulerian elevation difference stats:")
        diff_euler_stats = malib.print_stats(diff_euler)
        diff_euler_med = diff_euler_stats[5]

    if True:
        print("Writing Eulerian elevation difference map")
        dst_fn = os.path.join(outdir, outprefix + '_dz_eul.tif')
        print(dst_fn)
        iolib.writeGTiff(diff_euler, dst_fn, dem1_ds, ndv=diffndv)

    if False:
        print("Writing Eulerian relative elevation difference map")
        diff_euler_rel = diff_euler - diff_euler_med
        dst_fn = os.path.join(outdir, outprefix + '_dz_eul_rel.tif')
        print(dst_fn)
        iolib.writeGTiff(diff_euler_rel, dst_fn, dem1_ds, ndv=diffndv)

    if False:
        print("Writing out DEM2 with median elevation difference removed")
        dst_fn = os.path.splitext(
            dem2_fn)[0] + '_med' + diff_euler_med + '.tif'
        print(dst_fn)
        iolib.writeGTiff(dem2 - diff_euler_med, dst_fn, dem1_ds, ndv=diffndv)

    if False:
        print("Writing Eulerian elevation difference percentage map")
        diff_euler_perc = 100.0 * diff_euler / dem1
        dst_fn = os.path.join(outdir, outprefix + '_dz_eul_perc.tif')
        print(dst_fn)
        iolib.writeGTiff(diff_euler_perc, dst_fn, dem1_ds, ndv=diffndv)

    return dst_fn