def extract_patches_from_raster():
    count = 0
    for raster_file in Path('./world_map').glob('**/*.tif'):
        data = gr.from_file(str(raster_file))
        raster_blocks = view_as_blocks(data.raster, (225, 225))
        for i in range(raster_blocks.shape[0]):
            for j in range(raster_blocks.shape[1]):
                raster_data = raster_blocks[i, j]

                src = cv2.pyrDown(raster_data,
                                  dstsize=(raster_data.shape[1] // 2,
                                           raster_data.shape[0] // 2))

                data_out_downsampled = gr.GeoRaster(
                    src,
                    data.geot,
                    nodata_value=data.nodata_value,
                    projection=data.projection,
                    datatype=data.datatype,
                )
                data_out_downsampled.to_tiff(
                    './data_downsampled_blurred/data_q' + str(count) + str(i) +
                    str(j))

                data_out = gr.GeoRaster(
                    raster_data,
                    data.geot,
                    nodata_value=data.nodata_value,
                    projection=data.projection,
                    datatype=data.datatype,
                )
                data_out.to_tiff('./data/data_q' + str(count) + str(i) +
                                 str(j))
                count += 1
Exemple #2
0
    def _resize_data(self, data, coef):
        """Fix of georasters.resize for correct management of incomplete
        GeoTIFF-s

        :param data: GeoRaster
        :param coef: coefficient > 0 for resizing
        """
        xlen, ylen = self.get_dimensions(data)
        new_shape = (int(xlen * coef), int(ylen * coef))
        order = 0 if coef <= 1 else 1
        raster2 = data.raster.copy()
        raster2 = raster2.astype(float)
        raster2[data.raster.mask] = np.nan
        raster2 = resize(raster2, new_shape, order=order, mode='constant',
                         cval=False)
        raster2 = np.ma.masked_array(raster2, mask=np.isnan(raster2),
                                     fill_value=data.raster.fill_value)
        raster2 = raster2.astype(int)
        raster2[raster2.mask] = data.nodata_value
        raster2.mask = np.logical_or(np.isnan(raster2.data),
                                     raster2.data == data.nodata_value)
        geot = list(data.geot)
        [geot[-1], geot[1]] = np.array([geot[-1], geot[1]]) \
            * data.shape / new_shape
        return gr.GeoRaster(raster2, tuple(geot),
                            nodata_value=data.nodata_value,
                            projection=data.projection,
                            datatype=data.datatype)
def resample_tif(tif_file, pixel_spacing=0.5):
    source = gdal.Open(tif_file)
    source.GetRasterBand(1).SetNoDataValue(-32767)
    wgs84 = osr.SpatialReference() # slopppy 
    wgs84.ImportFromEPSG(3413)     # only for polar stereographic!
    # Get the Geotransform vector
    geo_t = source.GetGeoTransform ()
    x_size = source.RasterXSize # Raster xsize
    y_size = source.RasterYSize # Raster ysize
    # Work out the boundaries of the new dataset in the target projection
    ulx, uly = geo_t[0], geo_t[3]
    lrx = geo_t[0] + geo_t[1]*x_size
    lry = geo_t[3] + geo_t[5]*y_size
    # Now, we create an in-memory raster
    mem_drv = gdal.GetDriverByName('MEM')
    # The size of the raster is given the new projection and pixel spacing
    # Using the values we calculated above. Also, setting it to store one band
    # and to use Float32 data type.
    dest = mem_drv.Create('', int((lrx - ulx)/pixel_spacing),             int((uly - lry)/pixel_spacing), 1, gdal.GDT_Float32)
    # Calculate the new geotransform
    new_geo = ( ulx, pixel_spacing, geo_t[2],                 uly, geo_t[4], -pixel_spacing )
    # Set the geotransform
    dest.SetGeoTransform(new_geo)
    dest.SetProjection(source.GetProjection())
    # Perform the projection/resampling 
    res = gdal.ReprojectImage(source, dest, None, None,
                gdal.GRA_Bilinear)
    graster = gr.GeoRaster(dest.GetRasterBand(1).ReadAsArray(),
                           dest.GetGeoTransform(),0,
                           wgs84,gdal.GDT_Float32)
    return graster
Exemple #4
0
def to_georaster(x):
    with MemoryFile(x) as memfile:
        ds = memfile.open()
        return gr.GeoRaster(ds.dataset_mask(),
                            geot=ds.get_transform(),
                            nodata_value=ds.meta['nodata'],
                            projection=epsg[str(ds.crs.to_epsg())],
                            datatype=ds.meta["dtype"])
Exemple #5
0
def test_union():
    import georasters as gr
    raster = os.path.join(DATA, 'pre1500.tif')
    data = gr.from_file(raster)
    (xmin, xsize, x, ymax, y, ysize) = data.geot
    data1 = gr.GeoRaster(data.raster[:data.shape[0] / 2, :],
                         data.geot,
                         nodata_value=data.nodata_value,
                         projection=data.projection,
                         datatype=data.datatype)
    data2 = gr.GeoRaster(
        data.raster[data.shape[0] / 2:, :],
        (xmin, xsize, x, ymax + ysize * data.shape[0] / 2, y, ysize),
        nodata_value=data.nodata_value,
        projection=data.projection,
        datatype=data.datatype)
    '''
    import matplotlib.pyplot as plt
    plt.figure()
    data1.plot()
    plt.savefig(os.path.join(DATA,'data1.png'))
    
    plt.figure()
    data2.plot()
    plt.savefig(os.path.join(DATA,'data2.png'))
    
    from rasterstats import zonal_stats
    import geopandas as gp
    import pandas as pd
    
    # Import shapefiles
    pathshp = os.path.join(DATA, 'COL.shp')
    dfcol=gp.GeoDataFrame.from_file(pathshp)
    pathshp = os.path.join(DATA, 'TUR.shp')
    dftur=gp.GeoDataFrame.from_file(pathshp)
    
    # Joint geopandas df
    df=dfcol.append(dftur)
    df.reset_index(drop=True,inplace=True)
    
    stats = zonal_stats(df, raster, copy_properties=True, all_touched=True, raster_out=True, opt_georaster=True)
    dfcol=pd.merge(dfcol,pd.DataFrame(data=stats), 
    
    '''
    assert (data1.union(data2).raster == data.raster).sum() == data.count()
def get_global_raster(scale):
    shape = np.asarray([180, 360]) * scale
    base = np.ma.ones(shape)
    desired_x_size = 360 / base.shape[1]
    desired_y_size = 180 / base.shape[0]

    geot = (-180.0, desired_x_size, 0.0, 90.0, 0.0, -desired_y_size)
    (xmin, xsize, x, ymax, y, ysize) = geot
    raster = gr.GeoRaster(base, geot, nodata_value=0.0, fill_value=0.0,
                          projection="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
    return raster
Exemple #7
0
    def Segmentation(self, List_P):

        #List_P= [(P1_x, P1_y), (P2_x, P2_y), (P3_x, P3_y)] # Pixels not geocordinate
        # Sort Order of polygon points
        center = (np.mean([point[0] for point in List_P]), np.mean([point[1] for point in List_P]))
        List_P = sorted(List_P, key = lambda point: ((-np.pi * 3/4) - np.arctan2((point[1] - center[1]), (point[0] - center[0]))) % (2*np.pi))

        eps = 5

        while (min([f[0] for f in List_P]) - eps < 0) or (min([f[1] for f in List_P]) - eps < 0) or (max([f[1] for f in List_P]) + eps > self.im_red.raster.shape[0]) or (max([f[0] for f in List_P]) + eps > self.im_red.raster.shape[1]):
            eps -= 1
            #print("Activado epsilon")

        x_rect = np.uint(min([f[0] for f in List_P]) - eps)
        y_rect = np.uint(min([f[1] for f in List_P]) - eps)
        h_rect = np.uint(max([f[1] for f in List_P]) - min([f[1] for f in List_P]) + 2 * eps)
        w_rect = np.uint(max([f[0] for f in List_P]) - min([f[0] for f in List_P]) + 2 * eps)


        List_P = [(x - x_rect, y - y_rect) for x,y in List_P]
        poly = path.Path(List_P)

        xv,yv = np.meshgrid(range(w_rect), range(h_rect))
        flags = ~poly.contains_points(np.hstack((xv.flatten()[:,np.newaxis], yv.flatten()[:,np.newaxis])))

        list_rasters  = []

        for  Im in self.list_images():

            (xmin, xsize, x, ymax, y, ysize) = Im.geot
            I = Im.raster[y_rect: y_rect + h_rect, x_rect : x_rect + w_rect].copy()
            I[flags.reshape(I.shape)] = np.nan
            new_Im = gr.GeoRaster(cv2.copyMakeBorder(I, 1, 1, 1, 1, cv2.BORDER_CONSTANT, value= np.nan),
                                 (xmin + xsize * (w_rect + 1), xsize, x, ymax + ysize * (h_rect + 1), y, ysize),
                                 nodata_value=Im.nodata_value,
                                 projection=Im.projection,
                                 datatype=Im.datatype)

            #new_Im.raster[flags.reshape(new_Im.raster.shape)] = np.nan

            list_rasters.append(new_Im.copy())




        im_seg = Image_Multi()
        im_seg.load_images(im_red = list_rasters[0], im_green = list_rasters[1], im_blue = list_rasters[2],
                           im_nir = list_rasters[3], im_rededge = list_rasters[4])

        im_seg.list_P =  List_P

        return im_seg
Exemple #8
0
 def merge(self, array=None, **kwargs):
     """Wrapper for georasters.merge that simplifies merging raster segments returned by parallel operations."""
     try:
         array = [
             georasters.GeoRaster(i,
                                  self.geot,
                                  nodata_value=self.ndv,
                                  projection=self.projection,
                                  datatype=self.array.dtype) for i in array
         ]
         self.array = georasters.merge(array)
     except Exception as e:
         raise e
Exemple #9
0
    def Segmentation(self, List_P):
        #List_P= [(P1_x, P1_y), (P2_x, P2_y)]
        epsilon = 0

        x_rect = min([f[0] for f in List_P]) - epsilon
        y_rect = min([f[1] for f in List_P]) - epsilon
        h_rect = max([f[1]
                      for f in List_P]) - min([f[1]
                                               for f in List_P]) + 2 * epsilon
        w_rect = max([f[0]
                      for f in List_P]) - min([f[0]
                                               for f in List_P]) + 2 * epsilon

        List_P = [(x - x_rect, y - y_rect) for x, y in List_P]
        poly = path.Path(List_P)

        xv, yv = np.meshgrid(range(w_rect), range(h_rect))
        flags = ~poly.contains_points(
            np.hstack(
                (xv.flatten()[:, np.newaxis], yv.flatten()[:, np.newaxis])))

        list_rasters = []

        for Im in self.list_images():

            (xmin, xsize, x, ymax, y, ysize) = Im.geot

            new_Im = gr.GeoRaster(Im.raster[y_rect:y_rect + h_rect,
                                            x_rect:x_rect + w_rect].copy(),
                                  (xmin + xsize * w_rect, xsize, x,
                                   ymax + ysize * h_rect, y, ysize),
                                  nodata_value=Im.nodata_value,
                                  projection=Im.projection,
                                  datatype=Im.datatype)

            new_Im.raster[flags.reshape(new_Im.raster.shape)] = np.nan

            list_rasters.append(new_Im.copy())

        im_seg = Image_Multi()
        im_seg.load_images(im_red=list_rasters[0],
                           im_green=list_rasters[1],
                           im_blue=list_rasters[2],
                           im_nir=list_rasters[3],
                           im_rededge=list_rasters[4])

        return im_seg
Exemple #10
0
    def RGB(self, lim = 4000):
        #Function return RGB GeoRaster

        # Bounded values
        Z = np.zeros((self.im_red.raster.shape[0], self.im_red.raster.shape[1], 3))
        Z[:,:,0] = self.im_red.raster.copy()
        Z[:,:,1] = self.im_green.raster.copy()
        Z[:,:,2] = self.im_blue.raster.copy()

        Z[Z[:, :, 0] > lim] = lim
        Z[Z[:, :, 1] > lim] = lim
        Z[Z[:, :, 2] > lim] = lim
        Z[:, :, 0] = Z[:, :, 0] / (np.nanmax(Z[:, :, 0]) - np.nanmin(Z[:, :, 0]))
        Z[:, :, 1] = Z[:, :, 1] / (np.nanmax(Z[:, :, 1]) - np.nanmin(Z[:, :, 1]))
        Z[:, :, 2] = Z[:, :, 2] / (np.nanmax(Z[:, :, 2]) - np.nanmin(Z[:, :, 2]))
        Z[np.isnan(self.im_red.raster)] = np.nan

        (xmin, xsize, x, ymax, y, ysize) = self.im_red.geot

        return gr.GeoRaster(Z.copy(),(xmin, xsize, x, ymax, y, ysize),
                            nodata_value=self.im_red.nodata_value,
                            projection=self.im_red.projection,
                            datatype=self.im_red.datatype)
afr_cities.plot(ax=ax, markersize=.2, color='yellow')
ax.set_title('1 decimal degree buffer \n Major cities in Africa', fontsize = 12)
ax.set_axis_off()

# %% [markdown] Collapsed="false"
# # Raster Data 

# %% Collapsed="false"
raster = 'data/res03_crav6190h_sihr_cer.tif'

# %% Collapsed="false"
# Get info on raster
NDV, xsize, ysize, GeoT, Projection, DataType = gr.get_geo_info(raster)

grow = gr.load_tiff(raster)
grow = gr.GeoRaster(grow, GeoT, projection = Projection)

# %% Collapsed="false"
f, ax = plt.subplots(1, figsize=(13, 11))
grow.plot(ax = ax, cmap = 'YlGn_r')
ax.set_title('GAEZ Crop Suitability Measures')
ax.set_axis_off()

# %% [markdown] Collapsed="false"
# ## Clipping Raster 

# %% Collapsed="false"
brazil = countries.query('ADMIN == "Brazil"')

# %% Collapsed="false"
grow_clip = grow.clip(brazil)[0]
Exemple #12
0
def watershed(flow_dir_file, lake_data, val=47):
    """
    __orig_author__ =  Rdebbout
    
    Description
    ----------
    given a flow direction grid, develop tif representing lake watershed

    Parameters
    ----------
    flow_dir_file : grid file representing flow direction.  DIR file within HydroSHEDS
        
    lake_data   : object representing lake information including id and pour point lat/lon

    val : value to set watershed cells 

    Output
    ---------
    tif file of a lake's watershed including value attribute table
    
    """

    #get information about original flow direction raster
    #NDV = no data values    , xysize= raster size , tf = geotransform
    NDV, xsize, ysize, tf, Projection, DataType = gr.get_geo_info(
        flow_dir_file)
    #print (tf)

    #load into georaster from source file
    arr = gr.from_file(flow_dir_file)
    (xmin, xsize, x, ymax, y, ysize) = arr.geot

    #get pour point lon and lat from lake object
    pp_lon, pp_lat = lake_data.pour_pt_lon, lake_data.pour_pt_lat

    # Function to map location in pixel of raster array: https://github.com/ozak/georasters/blob/master/georasters/georasters.py
    here = gr.map_pixel(pp_lon, pp_lat, xsize, ysize, xmin, ymax)
    init = []
    init = ring_cells(here)

    hold = []
    temp_hold = eval_ring(init, arr)
    hold = temp_hold

    #Altered this to deal with an issue when iterating across multiple lakes in original code
    #for every cell in ring evaluate if it is flowing to the pour point, if so add it to the hold, temp_hold continues until exhausted
    while len(temp_hold) > 0:
        for h in temp_hold:
            init = ring_cells(h)
            temp_hold = eval_ring(init, arr)
            hold += temp_hold

    #Add target cell
    hold.append(here)
    hold = list(set(hold))

    # try to update transform info(tf) and shrink array
    dd = np.array(hold)
    r_min, col_min = np.amin(dd, axis=0)
    r_max, col_max = np.amax(dd, axis=0)

    #added step for WGS84 data that is not projected
    lon, lat = gr.map_pixel_inv(r_min, col_min, tf[1], tf[-1], tf[0], tf[3])

    # shift transform to reduce NoData in the output raster
    shifted_tf = (lon, tf[1], tf[2], lat, tf[4], tf[5])

    # insert val into the cells of the raster that represent watershed
    out = np.zeros(arr.shape)
    for idx in hold:
        out[idx] = val

    #plus 1 deals with index starting at 0,  these are counts of rows, columns
    new = out[r_min:(r_max + 1), col_min:(col_max + 1)]

    go = gr.GeoRaster(new, shifted_tf, 0)
    go.projection = Projection
    go.datatype = DataType

    #Set name of files and create
    lk_id = str(lake_data.id)

    #create tif file
    go.to_tiff(f"output/lkshed/{lk_id}_watershed")
    df = make_rat(f"output/lkshed/{lk_id}_watershed.tif")
    #export value attribute table
    df2dbf(df, f"output/lkshed/{lk_id}_watershed.tif.vat.dbf")

    # #cleanup to help take care of issues on iterative processing
    # arr = 0
    go = None
    here = None
    arr = None
    out = None
    new = None
    dd = None
    shifted_tf = None
    gc.collect()
def main():
    precip_data = gr.from_file(os.path.expanduser("~/Downloads/datasets/chelsea/CHELSA_bio10_12.tif"))

    print("ocean map")
    # get the chelsea data mask to be used as the main ocean mask
    x_ranges = list(gen_ranges(-180, 180, 1))
    y_ranges = list(gen_ranges(90, -90, 1))
    slices = get_slices(precip_data, x_ranges, y_ranges)
    precip_ag = aggregate_slices(slices, filter_masked)
    chelsea_mask = precip_ag.mask

    # load shapefiles
    water_shape = geopandas.read_file(
        os.path.expanduser("~/Downloads/datasets/natural_earth/ne_50m_ocean/ne_50m_ocean.shp"))
    df_river = geopandas.read_file(os.path.expanduser(
        "~/Downloads/datasets/natural_earth/ne_50m_rivers_lake_centerlines_scale_rank/ne_50m_rivers_lake_centerlines_scale_rank.shp"))
    df_lake = geopandas.read_file(
        os.path.expanduser("~/Downloads/datasets/natural_earth/ne_50m_lakes/ne_50m_lakes.shp"))
    df_lake_historic = geopandas.read_file(
        os.path.expanduser("~/Downloads/datasets/natural_earth/ne_50m_lakes_historic/ne_50m_lakes_historic.shp"))

    # rasterize the shapefiles
    raster_1 = get_global_raster(1)
    ocean = rasterize_shapefile(water_shape, raster_1)

    lake_r = rasterize_shapefile(df_lake, raster_1)
    lake_h_r = rasterize_shapefile(df_lake_historic, raster_1)

    # clip out the caspian sea
    n = 41
    s = 54
    e = 234
    w = 226
    area_mask = np.zeros(lake_r.shape, dtype=np.bool)
    area_mask[n:s, w:e] = True
    sea_mask = ocean & area_mask

    # merge the rasters
    underwater = chelsea_mask | lake_r | lake_h_r | sea_mask

    # save the underwater mask
    np.save("./data/underwater_mask.npy", underwater)
    np.save("./data/ocean_mask.npy", chelsea_mask)

    # littoral cells
    conv = np.asarray([
        [0, 1, 0],
        [1, 0, 1],
        [0, 1, 0],
    ])

    lit = scipy.signal.convolve2d(chelsea_mask, conv, mode="same", boundary="wrap")
    lit = lit >= 1
    np.save("./data/littoral.npy", lit)

    # generate the desert map
    print("desert map")
    desert = precip_ag < 250
    np.save("./data/desert.npy", desert.data)

    # generate river map
    print("river map")
    river_rasterized = rasterize_shapefile(df_river, raster_1)
    np.save("./data/river.npy", river_rasterized)

    # generate elevation map
    print("elevation map")
    height = gr.from_file(os.path.expanduser("~/Downloads/datasets/elevation/one_deg_height.tif")).raster
    np.save("./data/height.npy", height.data)
    stddev = gr.from_file(os.path.expanduser("~/Downloads/datasets/elevation/one_deg_stddev.tif")).raster
    np.save("./data/stddev.npy", stddev.data)

    # generate steppes map
    print("Steppes map")
    ecos_shape = geopandas.read_file(
        os.path.expanduser("~/Downloads/datasets/official_teow/official/wwf_terr_ecos.shp"))
    steppes = ecos_shape[ecos_shape["BIOME"] == 8]
    raster_1 = get_global_raster(1)
    steppes_rasterized = rasterize_shapefile(steppes, raster_1)
    np.save("./data/steppes.npy", steppes_rasterized)

    # Efective temperatures?
    print("effective temperature")
    effective_temperature = np.load("./data/effective_temperature_large.npy")
    effective_mask = np.load("./data/effective_temperature_large_mask.npy")
    effective_temperature = np.ma.array(effective_temperature, mask=effective_mask)
    chelsea_geot = (-180.00013888885002, 0.0083333333, 0.0, 83.99986041515001, 0.0, -0.0083333333)
    raster = gr.GeoRaster(effective_temperature, chelsea_geot)
    et_ag = aggregate_grid(raster, x_ranges, y_ranges)
    np.save("./data/effective_temperature.npy", et_ag.data)
    # terrestrial plant threshold
    tpt = et_ag > 12.75
    np.save("./data/terrestrial_plant_threshold.npy", tpt.data)

    # agriculture thresholds
    print("agriculture")
    agriculture = tpt & (desert == False) | (river_rasterized & tpt)
    np.save("./data/agriculture.npy", agriculture.data)
Exemple #14
0
gmax100 = gmax.copy()
gmax150 = gmax.copy()
gmax200 = gmax.copy()
gmax250 = gmax.copy()

gmax50[gmax50 < 50] = 0
gmax100[gmax100 < 100] = 0
gmax150[gmax150 < 150] = 0
gmax200[gmax200 < 200] = 0
gmax250[gmax250 < 250] = 0

#grad *= 255.0 / np.max(grad)  # normalize (Q&D)

output_gr = gr.GeoRaster(gmax50,
                         T1_gr.geot,
                         nodata_value=ndv,
                         projection=T1_gr.projection,
                         datatype=T1_gr.datatype)

output_gr.to_tiff('./output/k50')

output_gr = gr.GeoRaster(gmax100,
                         T1_gr.geot,
                         nodata_value=ndv,
                         projection=T1_gr.projection,
                         datatype=T1_gr.datatype)

output_gr.to_tiff('./output/k100')

output_gr = gr.GeoRaster(gmax150,
                         T1_gr.geot,
Exemple #15
0
import georasters
import numpy as np
from osgeo import osr

DATA = os.path.join(os.path.dirname(georasters.__path__[0]), "tests/data")
raster = os.path.join(DATA, 'pre1500.tif')

# Create rasters
projection = osr.SpatialReference()
projection.ImportFromEPSG(4326)

# Example that works correctly
# Raster 1
A = np.array([[1]])
A1 = georasters.GeoRaster(A, (0, 1, 0, 0, 0, -1),
                          nodata_value=-1,
                          projection=projection)
# Raster 2
B = np.array([[3]])
B1 = georasters.GeoRaster(B, (2, 1, 0, -1, 0, -1),
                          nodata_value=-1,
                          projection=projection)

# Union
C1 = A1.union(B1)

# Expected
C = np.array([[1, -1, -1], [-1, -1, 3]])
CE = georasters.GeoRaster(C, (0, 1, 0, 0, 0, -1),
                          nodata_value=-1,
                          projection=projection)
Exemple #16
0
# Find c
c = L - (a * (l - b)**2)

# Process raster
bcet_raster = a * ((raster_processed - b)**2) + c

print('New average value:')
print(bcet_raster.mean())  # should be 110!

#
# Output
#

output_gr = gr.GeoRaster(bcet_raster,
                         raster_clip[0].geot,
                         nodata_value=ndv,
                         projection=raster_clip[0].projection,
                         datatype=raster_clip[0].datatype)

output_dir_full = os.path.join(output_dir, run_title)

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

new_path = os.path.join(output_dir_full, run_title + '_' + band_name)
print('Outputing ' + new_path + ' ...')
# Make Geotiff
output_gr.to_tiff(new_path)

# Add some metadata
Exemple #17
0
 def to_georaster(self):
     return (georasters.GeoRaster(self.array,
                                  self.geot,
                                  nodata_value=self.ndv,
                                  projection=self.projection,
                                  datatype=self.array.dtype))
Exemple #18
0
T3 = r"./output/inyo_bcets/20151026_mojave_bcet/20151026_mojave_bcet_B1.tif"
T4 = r"./output/inyo_bcets/20160302_mojave_bcet/20160302_mojave_bcet_B1.tif"
T5 = r"./output/inyo_bcets/20160926_mojave_bcet/20160926_mojave_bcet_B1.tif"
T6 = r"./output/inyo_bcets/20170727_mojave_bcet/20170727_mojave_bcet_B1.tif"
T7 = r"./output/inyo_bcets/20170913_mojave_bcet/20170913_mojave_bcet_B1.tif"

T1_gr = gr.from_file(T1)
T2_gr = gr.from_file(T2)
T3_gr = gr.from_file(T3)
T4_gr = gr.from_file(T4)
T5_gr = gr.from_file(T5)
T6_gr = gr.from_file(T6)
T7_gr = gr.from_file(T7)

ndv, xsize, ysize, geot, projection, datatype = gr.get_geo_info(T1) # Raster information

Tstack = np.dstack((T1_gr.raster,T2_gr.raster,T3_gr.raster,T4_gr.raster,T5_gr.raster,T6_gr.raster,T7_gr.raster))

def difference(x):
	return np.max(x)-np.min(x)

Rdiff = np.apply_along_axis(difference,axis=2, arr=Tstack)

output_gr = gr.GeoRaster(Rdiff,
     T1_gr.geot,
     nodata_value=ndv,
     projection=T1_gr.projection,
     datatype=T1_gr.datatype)

output_gr.to_tiff('./output/diff')
def clip_gr(raster: gr.GeoRaster):
    """ Take a georaster and get a slice without a pesky edge """
    data = raster.raster[:-1,:-1]
    new_raster = gr.GeoRaster(data, raster.geot, raster.nodata_value,
                              projection=raster.projection, datatype=raster.datatype)
    return new_raster