Ejemplo n.º 1
0
def _sindex_drain_points(parm_dict):
    # for each drain point in the drain points shape file find the cell value in the combined stability index grid file
    # and use that value to populate the corresponding row in the drainpoints table
    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    dataSource = driver.Open(parm_dict[ParameterNames.drain_points_file], 1)
    layer = dataSource.GetLayer()
    layerDefn = layer.GetLayerDefn()
    fld_index_graipdid = layerDefn.GetFieldIndex('GRAIPDID')

    si_grid = gdal.Open(parm_dict[ParameterNames.csi_grid_file])
    si_band = si_grid.GetRasterBand(1)

    road_impact = False
    if parm_dict[ParameterNames.demang_file]:
        road_impact = True

    field_to_create = 'SIR' if road_impact else 'SI'
    try:
        #delete field if it exists in drainpoints shapefile
        fld_index_dp = layerDefn.GetFieldIndex(field_to_create)
        if fld_index_dp > 0:
            layer.DeleteField(fld_index_dp)

        # add a new field (column) to the attribute table of drainpoints shapefile
        layer.CreateField(ogr.FieldDefn(field_to_create, ogr.OFTReal))

        fld_index_dp = layerDefn.GetFieldIndex(field_to_create)
    except:
        pass

    try:
        conn = pyodbc.connect(utils. MS_ACCESS_CONNECTION % parm_dict[ParameterNames.mdb])
        cursor = conn.cursor()

        for feature in layer:
            geom = feature.GetGeometryRef()
            total_points = geom.GetPointCount()
            if total_points > 0:
                # lookup grid cell at drain point
                row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(0), geom.GetY(0), si_grid)
                si_cell_data = si_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)
                graipdid = feature.GetFieldAsInteger(fld_index_graipdid)
                dp_row = cursor.execute("SELECT * FROM DrainPoints WHERE GRAIPDID=%d" % graipdid).fetchone()

                if dp_row:
                    if si_cell_data[0][0] == si_band.GetNoDataValue():
                        if road_impact:
                            dp_row.SIR = -9999
                        else:
                            dp_row.SI = -9999
                    else:
                        if road_impact:
                            dp_row.SIR = float(si_cell_data[0][0])
                        else:
                            dp_row.SI = float(si_cell_data[0][0])

                    if road_impact:
                        update_sql = "UPDATE DrainPoints SET SIR=? WHERE GRAIPDID=?"
                        data = (dp_row.SIR, dp_row.GRAIPDID)
                    else:
                        update_sql = "UPDATE DrainPoints SET SI=? WHERE GRAIPDID=?"
                        data = (dp_row.SI, dp_row.GRAIPDID)

                    cursor.execute(update_sql, data)

                    # write si data to drainpoints shapefile
                    feature.SetField(fld_index_dp, data[0])
                    # rewrite the feature to the layer - this will in fact save the data to the file
                    layer.SetFeature(feature)

            geom = None

        conn.commit()
    except:
        raise
    finally:
        # cleanup
        if conn:
            conn.close()

        if dataSource:
            dataSource.Destroy()
Ejemplo n.º 2
0
def compute_mass_potential(graip_db, dp_shp, slpd, alpha, si=None, sic=None, dist=None):
    conn = pyodbc.connect(utils.MS_ACCESS_CONNECTION % graip_db)
    cursor = conn.cursor()
    slpd_gdal = gdal.Open(slpd)
    slpd_gdal_band = slpd_gdal.GetRasterBand(1)

    if si:
        si_gdal = gdal.Open(si)
        si_gdal_band = si_gdal.GetRasterBand(1)

    if sic:
        sic_gdal = gdal.Open(sic)
        sic_gdal_band = sic_gdal.GetRasterBand(1)

    if dist:
        dist_gdal = gdal.Open(dist)
        dist_gdal_band = dist_gdal.GetRasterBand(1)

    # open the drainpoints shapefile
    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    dataSource = driver.Open(dp_shp, 1)
    layer = dataSource.GetLayer()

    try:
        # for each drain point in shape file
        for dp in layer:
            geom = dp.GetGeometryRef()

            # find grid row and col corresponding to drain point
            row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(0), geom.GetY(0), slpd_gdal)
            geom = None
            # get the id of the drain point from shape file
            graipdid = dp.GetField('GRAIPDID')
            # get current grid cell data
            current_cell_slope_data = slpd_gdal_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)
            if si:
                current_cell_si_data = si_gdal_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)

            if sic:
                current_cell_sic_data = sic_gdal_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)

            if dist:
                current_cell_dist_data = dist_gdal_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)

            dp_row = cursor.execute("SELECT * FROM DrainPoints WHERE GRAIPDID=%d" % graipdid).fetchone()
            if dp_row:
                if current_cell_slope_data[0][0] != slpd_gdal_band.GetNoDataValue():
                    dp_row.Slope = float(current_cell_slope_data[0][0])
                    dp_row.ESI = dp_row.ELength * math.pow(dp_row.Slope, alpha)
                else:
                    dp_row.Slope = utils.NO_DATA_VALUE
                    dp_row.ESI = utils.NO_DATA_VALUE

                update_sql = "UPDATE DrainPoints SET Slope=?, ESI=? WHERE GRAIPDID=?"
                data = (dp_row.Slope, dp_row.ESI, dp_row.GRAIPDID)
                cursor.execute(update_sql, data)
                if si:
                    if current_cell_si_data[0][0] != si_gdal_band.GetNoDataValue():
                        dp_row.SI = float(current_cell_si_data[0][0])
                    else:
                        dp_row.SI = utils.NO_DATA_VALUE

                    update_sql = "UPDATE DrainPoints SET SI=? WHERE GRAIPDID=?"
                    data = (dp_row.SI, dp_row.GRAIPDID)
                    cursor.execute(update_sql, data)
                if sic:
                    if current_cell_sic_data[0][0] != sic_gdal_band.GetNoDataValue():
                        dp_row.SIR = float(current_cell_sic_data[0][0])
                    else:
                        dp_row.SIR = utils.NO_DATA_VALUE

                    update_sql = "UPDATE DrainPoints SET SIR=? WHERE GRAIPDID=?"
                    data = (dp_row.SIR, dp_row.GRAIPDID)
                    cursor.execute(update_sql, data)

                if dist:
                    if current_cell_dist_data[0][0] != dist_gdal_band.GetNoDataValue():
                        dp_row.DistToStream = float(current_cell_dist_data[0][0])
                    else:
                        dp_row.DistToStream = utils.NO_DATA_VALUE

                    update_sql = "UPDATE DrainPoints SET DistToStream=? WHERE GRAIPDID=?"
                    data = (dp_row.DistToStream, dp_row.GRAIPDID)
                    cursor.execute(update_sql, data)
        conn.commit()
    except:
        raise
    finally:
        # cleanup
        if conn:
            conn.close()

        if dataSource:
            dataSource.Destroy()
Ejemplo n.º 3
0
def _create_weight_grids_from_points(weight_min_raster_file, weight_max_raster_file, params_dict):
    # Reference: c++ function: createweightgridfrompoints

    """
    Creates the temporary weight grids (min and max) to be used with TauDEM areadinf function

    :param weight_min_raster_file: temporary weight grid file to which minimum weight data needs to be written
    :param weight_max_raster_file: temporary weight grid file to which maximum weight data needs to be written
    :param params_dict: a dictionary containing user parameter inputs for stability index computation
    :return: None
    """

    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    data_source = driver.Open(params_dict[ParameterNames.drain_points_file], 1)
    layer = data_source.GetLayer()
    layer_defn = layer.GetLayerDefn()
    try:
        layer_defn.GetFieldIndex('GRAIPDID')
    except:
        data_source.Destroy()
        raise utils.ValidationException("Invalid drain points shape file. Attribute 'GRAIPDID' is missing in "
                                        "this file.")

    try:
        conn = pyodbc.connect(utils.MS_ACCESS_CONNECTION % params_dict[ParameterNames.mdb])
        cursor = conn.cursor()
        dp_rows = cursor.execute("SELECT * FROM DrainPoints ORDER BY GRAIPDID ASC").fetchall()
        dp_type_rows = cursor.execute("SELECT * FROM DrainTypeDefinitions").fetchall()

        accum_rmax = {}
        accum_rmin = {}

        for row in dp_rows:
            accum_area = 0
            matching_dp_type_row = [dpt_row for dpt_row in dp_type_rows if dpt_row.DrainTypeID == row.DrainTypeID][0]

            if matching_dp_type_row.CCSI:
                accum_area = row.ELength * float(params_dict[ParameterNames.road_width])

            accum_rmin[row.GRAIPDID] = accum_area * float(params_dict[ParameterNames.min_additional_runoff])
            accum_rmax[row.GRAIPDID] = accum_area * float(params_dict[ParameterNames.max_additional_runoff])

        # open the output temp weight grid files to write data to it
        weight_min_grid_file = gdal.Open(weight_min_raster_file, GA_Update)
        weight_max_grid_file = gdal.Open(weight_max_raster_file, GA_Update)

        # for each drain point in shape file
        for dp in layer:
            geom = dp.GetGeometryRef()

            # find weight grid row and col corresponding to drain point
            row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(0), geom.GetY(0), weight_min_grid_file)
            geom = None
            # get the id of the drain point from shape file
            graipdid = dp.GetField('GRAIPDID')

            def _write_weight_to_grid(grid_file, weight_values):
                # create a 2D array to store weight data
                weight_array = np.zeros((1, 1), dtype=np.float32)
                grid_file_band = grid_file.GetRasterBand(1)
                # get current grid cell data
                current_cell_data = grid_file_band.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)
                if current_cell_data[0][0] != utils.NO_DATA_VALUE:
                    weight_array[0][0] = weight_values[graipdid]

                # here we are writing to a specific cell of the grid
                grid_file_band.WriteArray(weight_array, xoff=col, yoff=row)

            _write_weight_to_grid(weight_min_grid_file, accum_rmin)
            _write_weight_to_grid(weight_max_grid_file, accum_rmax)

        grid_file_band = weight_min_grid_file.GetRasterBand(1)
        grid_file_band.FlushCache()
        grid_file_band = weight_max_grid_file.GetRasterBand(1)
        grid_file_band.FlushCache()

    except:
        raise
    finally:
        if data_source:
            data_source.Destroy()

        if conn:
            conn.close()

        weight_min_grid_file = None
        weight_max_grid_file = None
Ejemplo n.º 4
0
def compute_length_elevation_interpolation(rd_shapefile, input_dem):
    """
    Calculates road segment length and elevation and writes to roadlines shapefile

    :param rd_shapefile: Path to roadlines shapefile
    :param input_dem: Path to dem file
    :return: None
    """
    # DEBUG:
    print("Computing length/elevation interpolation...")

    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    dataSource = driver.Open(rd_shapefile, 1)
    layer = dataSource.GetLayer()
    layerDefn = layer.GetLayerDefn()

    dem = gdal.Open(input_dem)
    dem_nx = dem.RasterXSize
    dem_ny = dem.RasterYSize
    gt = dem.GetGeoTransform()
    dem_band = dem.GetRasterBand(1)

    # Compute mid-point grid spacings
    # ref: http://gis.stackexchange.com/questions/7611/bilinear-interpolation-of-point-data-on-a-raster-in-python
    # gt[0] dem originX
    # gt[3] dem originY
    # gt[1] dem cell width (in pixel)
    # gt[5] dem cell height (in pixel)

    ax = array([gt[0] + ix * gt[1] + gt[1] / 2.0 for ix in range(dem_nx)])
    ay = array([gt[3] + iy * gt[5] + gt[5] / 2.0 for iy in range(dem_ny)])

    try:
        # delete field "Length" if it exists
        fld_index = layerDefn.GetFieldIndex('Length')
        if fld_index > 0:
            layer.DeleteField(fld_index)

        # delete "Range" if it exists
        fld_index = layerDefn.GetFieldIndex('Range')
        if fld_index > 0:
            layer.DeleteField(fld_index)
    except:
        pass

    # add a new field (column) 'Length' to the attribute table
    layer.CreateField(ogr.FieldDefn('Length', ogr.OFTReal))
    fld_index_length = layerDefn.GetFieldIndex('Length')

    # add a new field (column) 'Range' to the attribute table
    layer.CreateField(ogr.FieldDefn('Range', ogr.OFTReal))
    fld_index_range = layerDefn.GetFieldIndex('Range')

    for feature in layer:
        try:
            geom = feature.GetGeometryRef()
            if geom:
                total_points = geom.GetPointCount()
                # write length value to shapefile
                # feature.SetField(fld_index_length, geom.Length())
                rd_length = geom.Length()
                if total_points > 0:
                    # calculate range from the elevation of 2 end points of the road segment
                    # using interpolation

                    # first find the row, col of the dem corresponding to
                    # the fist point of the road segment
                    row, col = utils.get_coordinate_to_grid_row_col(
                        geom.GetX(0), geom.GetY(0), dem)
                    # get the dem cells corresponding to row, col needed to generate the interpolation function
                    dem_array = dem_band.ReadAsArray(xoff=col,
                                                     yoff=row,
                                                     win_xsize=2,
                                                     win_ysize=2)
                    # define the interpolation function
                    bilinterp = interpolate.interp2d(ax[col:col + 2],
                                                     ay[row:row + 2],
                                                     dem_array,
                                                     kind='linear')

                    # find the elevation of the 1st point using the interpolation function
                    elevation_1 = bilinterp(geom.GetX(0), geom.GetY(0))[0]

                    # find the row, col of the dem corresponding to
                    # the 2nd point of the road segment
                    row, col = utils.get_coordinate_to_grid_row_col(
                        geom.GetX(total_points - 1),
                        geom.GetY(total_points - 1), dem)
                    # get the dem cells corresponding to row, col needed to generate the interpolation function
                    dem_array = dem_band.ReadAsArray(xoff=col,
                                                     yoff=row,
                                                     win_xsize=2,
                                                     win_ysize=2)
                    # define the interpolation function
                    bilinterp = interpolate.interp2d(ax[col:col + 2],
                                                     ay[row:row + 2],
                                                     dem_array,
                                                     kind='linear')

                    # find the elevation of the 1st point using the interpolation function
                    elevation_2 = bilinterp(geom.GetX(total_points - 1),
                                            geom.GetY(total_points - 1))[0]
                    rd_range = abs(elevation_2 - elevation_1)
                else:
                    rd_range = 0  # sometimes shape/feature have no points - in that case we say range is zero
            else:
                rd_length = 0
                rd_range = 0

            # write length value to shapefile
            feature.SetField(fld_index_length, rd_length)
            # write range value to shapefile
            feature.SetField(fld_index_range, rd_range)

            # rewrite the feature to the layer - this will in fact save the data
            layer.SetFeature(feature)
            geom = None

        except Exception as ex:
            dataSource.Destroy()
            raise

    # close datasource
    dataSource.Destroy()
    # DEBUG:
    print("Finished computing length/elevation interpolation...")
Ejemplo n.º 5
0
def create_drainpoint_weighted_grid(input_dem, graip_db, dpsi_gridfile,
                                    dp_shapefile, is_stream_connected):
    """
    Creates a new grid file with drain point sediment production data

    :param input_dem: Path to dem file
    :param graip_db: Path to graip database file
    :param dpsi_gridfile: Path the output grid file to which sediment data will be writen
    :param dp_shapefile: Path to drainpoint shapefile
    :param is_stream_connected: Flag(True/False) to indicate if sediment data grid file be created for all
    drainpoints or only stream connected points
    :return: None
    """

    # DEBUG:
    print("Starting to write sediment data to output grid file.")
    dataSource = None
    conn = None
    try:
        conn = pyodbc.connect(utils.MS_ACCESS_CONNECTION % graip_db)
        cursor = conn.cursor()
        # TODO: May be use the no data value from the input dem
        # (ref: http://www.gdal.org/classGDALRasterBand.html#adcca51d230b5ac848c43f1896293fb50)

        # create a new weighted tif file based on the dem file
        dem = gdal.Open(input_dem)
        geotransform = dem.GetGeoTransform()
        originX = geotransform[0]
        originY = geotransform[3]
        pixelWidth = geotransform[1]
        pixelHeight = geotransform[5]
        rows = dem.RasterYSize
        cols = dem.RasterXSize

        # DEBUG:
        print("Creating sediment output grid file.")
        driver = gdal.GetDriverByName(utils.GDALFileDriver.TifFile())
        number_of_bands = 1
        outRaster = driver.Create(dpsi_gridfile, cols, rows, number_of_bands,
                                  gdal.GDT_Float32)
        outRaster.SetGeoTransform(
            (originX, pixelWidth, 0, originY, 0, pixelHeight))

        # DEBUG:
        print("Initializing sediment output grid file with zeros.")

        # TODO: use the band Fill() method to initialize the raster (ref:http://www.gdal.org/classGDALRasterBand.html#a55bf20527df638dc48bf25e2ff26f353)
        # initialize the newly created tif file with zeros
        # grid_initial_data = np.zeros((rows, cols), dtype=np.float32)
        # grid_initial_data[:] = 0.0    # this causes memory error in case of big dem
        outband = outRaster.GetRasterBand(1)
        outband.SetNoDataValue(utils.NO_DATA_VALUE)
        # initialize the newly created tif file with zeros - this solves the memory error
        outband.Fill(0.0)
        #outband.WriteArray(grid_initial_data)
        # DEBUG:
        print("Finished initializing sediment grid file.")

        # set the projection of the tif file same as that of the dem
        outRasterSRS = osr.SpatialReference()
        outRasterSRS.ImportFromWkt(dem.GetProjectionRef())
        outRaster.SetProjection(outRasterSRS.ExportToWkt())

        # open the drainpoints shapefile
        driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
        dataSource = driver.Open(dp_shapefile, 1)
        layer = dataSource.GetLayer()

        # for each drain point in shape file
        # DEBUG:
        print("Looping over drain points in shapefile")
        for dp in layer:
            geom = dp.GetGeometryRef()

            # find grid row and col corresponding to drain point
            row, col = utils.get_coordinate_to_grid_row_col(
                geom.GetX(0), geom.GetY(0), dem)
            geom = None
            # get the id of the drain point from shape file
            graipdid = dp.GetField('GRAIPDID')

            def _write_sed_accum_to_grid():
                # create a 2D array to store sediment production data
                sed_array = np.zeros((1, 1), dtype=np.float32)

                # get current grid cell data
                current_cell_data = outband.ReadAsArray(xoff=col,
                                                        yoff=row,
                                                        win_xsize=1,
                                                        win_ysize=1)
                if current_cell_data[0][0] != utils.NO_DATA_VALUE:
                    sed_array[0][0] = current_cell_data[0][0] + dp_row.SedProd
                else:
                    sed_array[0][0] = dp_row.SedProd

                # here we are writing to a specific cell of the grid
                outband.WriteArray(sed_array, xoff=col, yoff=row)

            # find the drain point matching row from the DrainPoints db table
            dp_row = cursor.execute(
                "SELECT SedProd, StreamConnectID FROM DrainPoints WHERE GRAIPDID=?",
                graipdid).fetchone()
            if is_stream_connected:
                if dp_row.StreamConnectID == 2:
                    _write_sed_accum_to_grid()
            else:
                _write_sed_accum_to_grid()

        outband.FlushCache()
        # calculate raster statistics (min, max, mean, stdDev)
        outband.GetStatistics(0, 1)
        # DEBUG:
        print("Finished writing data to sediment grid file.")

    except:
        raise
    finally:
        if dataSource is not None:
            dataSource.Destroy()

        if conn:
            conn.close()

        dem = None
        outRaster = None
Ejemplo n.º 6
0
def compute_length_elevation_interpolation(rd_shapefile, input_dem):
    """
    Calculates road segment length and elevation and writes to roadlines shapefile

    :param rd_shapefile: Path to roadlines shapefile
    :param input_dem: Path to dem file
    :return: None
    """
    # DEBUG:
    print ("Computing length/elevation interpolation...")

    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    dataSource = driver.Open(rd_shapefile, 1)
    layer = dataSource.GetLayer()
    layerDefn = layer.GetLayerDefn()

    dem = gdal.Open(input_dem)
    dem_nx = dem.RasterXSize
    dem_ny = dem.RasterYSize
    gt = dem.GetGeoTransform()
    dem_band = dem.GetRasterBand(1)

    # Compute mid-point grid spacings
    # ref: http://gis.stackexchange.com/questions/7611/bilinear-interpolation-of-point-data-on-a-raster-in-python
    # gt[0] dem originX
    # gt[3] dem originY
    # gt[1] dem cell width (in pixel)
    # gt[5] dem cell height (in pixel)

    ax = array([gt[0] + ix*gt[1] + gt[1]/2.0 for ix in range(dem_nx)])
    ay = array([gt[3] + iy*gt[5] + gt[5]/2.0 for iy in range(dem_ny)])

    try:
        # delete field "Length" if it exists
        fld_index = layerDefn.GetFieldIndex('Length')
        if fld_index > 0:
            layer.DeleteField(fld_index)

        # delete "Range" if it exists
        fld_index = layerDefn.GetFieldIndex('Range')
        if fld_index > 0:
            layer.DeleteField(fld_index)
    except:
        pass

    # add a new field (column) 'Length' to the attribute table
    layer.CreateField(ogr.FieldDefn('Length', ogr.OFTReal))
    fld_index_length = layerDefn.GetFieldIndex('Length')

    # add a new field (column) 'Range' to the attribute table
    layer.CreateField(ogr.FieldDefn('Range', ogr.OFTReal))
    fld_index_range = layerDefn.GetFieldIndex('Range')

    for feature in layer:
        try:
            geom = feature.GetGeometryRef()
            if geom:
                total_points = geom.GetPointCount()
                # write length value to shapefile
                # feature.SetField(fld_index_length, geom.Length())
                rd_length = geom.Length()
                if total_points > 0:
                    # calculate range from the elevation of 2 end points of the road segment
                    # using interpolation

                    # first find the row, col of the dem corresponding to
                    # the fist point of the road segment
                    row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(0), geom.GetY(0), dem)
                    # get the dem cells corresponding to row, col needed to generate the interpolation function
                    dem_array = dem_band.ReadAsArray(xoff=col, yoff=row, win_xsize=2, win_ysize=2)
                    # define the interpolation function
                    bilinterp = interpolate.interp2d(ax[col:col+2], ay[row:row+2], dem_array,
                                                     kind='linear')

                    # find the elevation of the 1st point using the interpolation function
                    elevation_1 = bilinterp(geom.GetX(0), geom.GetY(0))[0]

                    # find the row, col of the dem corresponding to
                    # the 2nd point of the road segment
                    row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(total_points-1),
                                                                    geom.GetY(total_points-1), dem)
                    # get the dem cells corresponding to row, col needed to generate the interpolation function
                    dem_array = dem_band.ReadAsArray(xoff=col, yoff=row, win_xsize=2, win_ysize=2)
                    # define the interpolation function
                    bilinterp = interpolate.interp2d(ax[col:col+2], ay[row:row+2], dem_array,
                                                     kind='linear')

                    # find the elevation of the 1st point using the interpolation function
                    elevation_2 = bilinterp(geom.GetX(total_points-1), geom.GetY(total_points-1))[0]
                    rd_range = abs(elevation_2 - elevation_1)
                else:
                    rd_range = 0    # sometimes shape/feature have no points - in that case we say range is zero
            else:
                rd_length = 0
                rd_range = 0

            # write length value to shapefile
            feature.SetField(fld_index_length, rd_length)
            # write range value to shapefile
            feature.SetField(fld_index_range, rd_range)

            # rewrite the feature to the layer - this will in fact save the data
            layer.SetFeature(feature)
            geom = None

        except Exception as ex:
            dataSource.Destroy()
            raise

    # close datasource
    dataSource.Destroy()
    # DEBUG:
    print ("Finished computing length/elevation interpolation...")
Ejemplo n.º 7
0
def create_drainpoint_weighted_grid(input_dem, graip_db, dpsi_gridfile, dp_shapefile, is_stream_connected):
    """
    Creates a new grid file with drain point sediment production data

    :param input_dem: Path to dem file
    :param graip_db: Path to graip database file
    :param dpsi_gridfile: Path the output grid file to which sediment data will be writen
    :param dp_shapefile: Path to drainpoint shapefile
    :param is_stream_connected: Flag(True/False) to indicate if sediment data grid file be created for all
    drainpoints or only stream connected points
    :return: None
    """

    # DEBUG:
    print ("Starting to write sediment data to output grid file.")
    dataSource = None
    conn = None
    try:
        conn = pyodbc.connect(utils.MS_ACCESS_CONNECTION % graip_db)
        cursor = conn.cursor()
        # TODO: May be use the no data value from the input dem
        # (ref: http://www.gdal.org/classGDALRasterBand.html#adcca51d230b5ac848c43f1896293fb50)

        # create a new weighted tif file based on the dem file
        dem = gdal.Open(input_dem)
        geotransform = dem.GetGeoTransform()
        originX = geotransform[0]
        originY = geotransform[3]
        pixelWidth = geotransform[1]
        pixelHeight = geotransform[5]
        rows = dem.RasterYSize
        cols = dem.RasterXSize

        # DEBUG:
        print ("Creating sediment output grid file.")
        driver = gdal.GetDriverByName(utils.GDALFileDriver.TifFile())
        number_of_bands = 1
        outRaster = driver.Create(dpsi_gridfile, cols, rows, number_of_bands, gdal.GDT_Float32)
        outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight))

        # DEBUG:
        print ("Initializing sediment output grid file with zeros.")

        # TODO: use the band Fill() method to initialize the raster (ref:http://www.gdal.org/classGDALRasterBand.html#a55bf20527df638dc48bf25e2ff26f353)
        # initialize the newly created tif file with zeros
        # grid_initial_data = np.zeros((rows, cols), dtype=np.float32)
        # grid_initial_data[:] = 0.0    # this causes memory error in case of big dem
        outband = outRaster.GetRasterBand(1)
        outband.SetNoDataValue(utils.NO_DATA_VALUE)
        # initialize the newly created tif file with zeros - this solves the memory error
        outband.Fill(0.0)
        #outband.WriteArray(grid_initial_data)
        # DEBUG:
        print ("Finished initializing sediment grid file.")

        # set the projection of the tif file same as that of the dem
        outRasterSRS = osr.SpatialReference()
        outRasterSRS.ImportFromWkt(dem.GetProjectionRef())
        outRaster.SetProjection(outRasterSRS.ExportToWkt())

        # open the drainpoints shapefile
        driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
        dataSource = driver.Open(dp_shapefile, 1)
        layer = dataSource.GetLayer()

        # for each drain point in shape file
        # DEBUG:
        print ("Looping over drain points in shapefile")
        for dp in layer:
            geom = dp.GetGeometryRef()

            # find grid row and col corresponding to drain point
            row, col = utils.get_coordinate_to_grid_row_col(geom.GetX(0), geom.GetY(0), dem)
            geom = None
            # get the id of the drain point from shape file
            graipdid = dp.GetField('GRAIPDID')

            def _write_sed_accum_to_grid():
                # create a 2D array to store sediment production data
                sed_array = np.zeros((1, 1), dtype=np.float32)

                # get current grid cell data
                current_cell_data = outband.ReadAsArray(xoff=col, yoff=row, win_xsize=1, win_ysize=1)
                if current_cell_data[0][0] != utils.NO_DATA_VALUE:
                    sed_array[0][0] = current_cell_data[0][0] + dp_row.SedProd
                else:
                    sed_array[0][0] = dp_row.SedProd

                # here we are writing to a specific cell of the grid
                outband.WriteArray(sed_array, xoff=col, yoff=row)

            # find the drain point matching row from the DrainPoints db table
            dp_row = cursor.execute("SELECT SedProd, StreamConnectID FROM DrainPoints WHERE GRAIPDID=?",
                                    graipdid).fetchone()
            if is_stream_connected:
                if dp_row.StreamConnectID == 2:
                    _write_sed_accum_to_grid()
            else:
                _write_sed_accum_to_grid()

        outband.FlushCache()
        # calculate raster statistics (min, max, mean, stdDev)
        outband.GetStatistics(0, 1)
        # DEBUG:
        print ("Finished writing data to sediment grid file.")

    except:
        raise
    finally:
        if dataSource is not None:
            dataSource.Destroy()

        if conn:
            conn.close()

        dem = None
        outRaster = None
def _sindex_drain_points(mdb, dp, si):
    # for each drain point in the drain points shape file find the cell value in the combined stability index grid file
    # and use that value to populate the corresponding row in the drainpoints table
    driver = ogr.GetDriverByName(utils.GDALFileDriver.ShapeFile())
    dataSource = driver.Open(dp, GA_Update)
    layer = dataSource.GetLayer()
    layerDefn = layer.GetLayerDefn()
    fld_index_graipdid = layerDefn.GetFieldIndex('GRAIPDID')

    si_grid = gdal.Open(si)
    si_band = si_grid.GetRasterBand(1)

    field_to_create = 'SI'
    try:
        #delete field if it exists in drainpoints shapefile
        fld_index_dp = layerDefn.GetFieldIndex(field_to_create)
        if fld_index_dp > 0:
            layer.DeleteField(fld_index_dp)

        # add a new field (column) to the attribute table of drainpoints shapefile
        layer.CreateField(ogr.FieldDefn(field_to_create, ogr.OFTReal))

        fld_index_dp = layerDefn.GetFieldIndex(field_to_create)
    except:
        pass

    try:
        conn = pyodbc.connect(utils.MS_ACCESS_CONNECTION % mdb)
        cursor = conn.cursor()

        for feature in layer:
            geom = feature.GetGeometryRef()
            total_points = geom.GetPointCount()
            if total_points > 0:
                # calculate range from the elevation of 2 end points of the road segment
                row, col = utils.get_coordinate_to_grid_row_col(
                    geom.GetX(0), geom.GetY(0), si_grid)
                si_cell_data = si_band.ReadAsArray(xoff=col,
                                                   yoff=row,
                                                   win_xsize=1,
                                                   win_ysize=1)
                graipdid = feature.GetFieldAsInteger(fld_index_graipdid)
                dp_row = cursor.execute(
                    "SELECT * FROM DrainPoints WHERE GRAIPDID=%d" %
                    graipdid).fetchone()

                if dp_row:
                    if si_cell_data[0][0] == si_band.GetNoDataValue():
                        dp_row.SI = -9999
                    else:
                        dp_row.SI = float(si_cell_data[0][0])

                    update_sql = "UPDATE DrainPoints SET SI=? WHERE GRAIPDID=?"
                    data = (dp_row.SI, dp_row.GRAIPDID)

                    cursor.execute(update_sql, data)

                    # write si data to drainpoints shapefile
                    feature.SetField(fld_index_dp, data[0])
                    # rewrite the feature to the layer - this will in fact save the data to the file
                    layer.SetFeature(feature)

            geom = None
        conn.commit()
    except:
        raise
    finally:
        # cleanup
        if conn:
            conn.close()

        if dataSource:
            dataSource.Destroy()