コード例 #1
0
def build_gadm28_tile_list(source_layer, is_test):

    logging.info('Building tile list')
    logging.info('checking extent of input geometry {}'.format(
        source_layer.input_dataset))

    # shapefile of tiles used to tsv aoi
    root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    tiles = fiona.open(
        os.path.join(root_dir, 'grid', 'lossdata_footprint_filter.geojson'),
        'r')

    # aoi we want to tsv
    source_file_ext = os.path.splitext(source_layer.input_dataset)[1]
    if source_file_ext in ['.rvrt', '.tif']:
        with rasterio.open(source_layer.input_dataset) as src:
            aoi_bounds = src.bounds
    elif source_file_ext == '':
        conn, cursor = pg_util.conn_to_postgis()

        extent_sql = 'SELECT ST_Extent(geom) FROM {}'.format(
            source_layer.input_dataset)
        cursor.execute(extent_sql)
        extent_text = cursor.fetchall()[0][0].replace('BOX(', '').replace(
            ')', '').replace(',', ' ')
        aoi_bounds = [float(x) for x in extent_text.split()]

    else:
        aoi_bounds = fiona.open(source_layer.input_dataset).bounds

    # select tiles that are inside of the bounding box of the aoi
    tiles_in_aoi = tiles.filter(bbox=aoi_bounds)

    for feat in tiles_in_aoi:
        # get the bounding box of the 1deg tile
        bbox = shape(feat['geometry']).bounds

        # get the tile id- used for naming
        # tile_id = feat['properties']['ulx_uly']
        tile_id = feat['properties']['ID']

        # build the tile object
        t = Tile(source_layer.input_dataset, source_layer.col_list, tile_id,
                 bbox)

        # add the tile bbox to the tile_list
        source_layer.tile_list.append(t)

    # if this is a test, only do one tile
    if is_test:
        source_layer.tile_list = source_layer.tile_list[0:1]
コード例 #2
0
def raster_intersect(q):
    # used only for source dataset + admin boundaries
    # all tile-to-tiles intersection is vector
    while True:
        output_layer, tile1, tile2 = q.get()

        conn, cursor = pg_util.conn_to_postgis()

        table_name = '{}_{}'.format(tile1.postgis_table, tile2.postgis_table)

        if pg_util.table_has_rows(cursor, tile1.postgis_table):

            # source: https://gis.stackexchange.com/a/19858/30899
            sql = ("CREATE TABLE {table_name} AS "
                   "SELECT (gv).val AS bound1, 1 AS bound2, 1 AS bound3, 1 as bound4, iso, id_1, id_2, (gv).geom AS geom "
                   "FROM (SELECT iso, id_1, id_2, ST_Intersection(rast, geom) AS gv "
                   "      FROM {table1}, {table2} "
                   "      WHERE ST_Intersects(rast, geom) "
                   "     ) foo "
                   "WHERE (gv).val > 0".format(table_name=table_name,
                         table1=tile1.postgis_table, table2=tile2.postgis_table))

            logging.info(sql)

            valid_intersect = True

            try:
                cursor.execute(sql)
                logging.info('Intersect for {} successful'.format(table_name))
            except Exception, e:
                valid_intersect = False
                logging.error('Error {} in sql statement {}'.format(sql, e))

            if valid_intersect:
                pg_util.fix_geom(table_name, cursor)

                if pg_util.table_has_rows(cursor, table_name):
                    output_tile = tile.Tile(None, None, tile1.tile_id, tile1.bbox, table_name)
                    output_layer.tile_list.append(output_tile)

        conn.commit()
        conn.close()

        q.task_done()
コード例 #3
0
def tabulate_area(q):
    while True:
        tile = q.get()

        conn, cursor = pg_util.conn_to_postgis()
        col_list = ['polyname', 'bound1', 'bound2',
                    'bound3', 'bound4', 'iso', 'id_1', 'id_2']
        col_str = ', '.join(col_list)

        sql = ("INSERT INTO aoi_area "
               "SELECT {c}, sum(ST_Area(geography(geom))) / 10000 AS area_poly_aoi "
               "FROM {t} "
               "GROUP BY {c} ".format(t=tile.postgis_table, c=col_str))

        cursor.execute(sql)
        conn.commit()

        conn.close()
        q.task_done()
コード例 #4
0
def load(zip_source):

    boundary_fields = [{
        'boundary_field1': 'boundary_field1'
    }, {
        'boundary_field2': 'boundary_field2'
    }]

    table_name = os.path.splitext(os.path.basename(zip_source))[0]
    if pg_util.check_table_exists(table_name):
        logging.info('{} data already in PostGIS'.format(zip_source))

    else:
        gadm28_shp = download_gadm28(zip_source)

        pg_util.insert_into_postgis(gadm28_shp, boundary_fields)

        conn, cursor = pg_util.conn_to_postgis()

        pg_util.fix_geom(table_name, cursor, False)

        conn.close()

        print "For whatever reason, we're unable to truly update " \
              "the input gadm geometry.\nPlease enter the postgres shell " \
              "and run UPDATE <gadm table name> SET geom = ST_CollectionExtract(" \
              "ST_MakeValid(geom), 3) WHERE ST_IsValid(geom) <> '1';"

        sys.exit()

    l = Layer(table_name, [])
    l.tile_list = [
        Tile(l.input_dataset, boundary_fields, None, None, l.input_dataset)
    ]

    return l
コード例 #5
0
def clip(q):
    while True:
        tile = q.get()

        conn_str = pg_util.build_ogr_pg_conn()
        col_str = pg_util.boundary_field_dict_to_sql_str(tile.col_list)

        if not tile.postgis_table:
            dataset_name = os.path.splitext(os.path.basename(tile.dataset))[0]
            tile.postgis_table = '_'.join([dataset_name, tile.tile_id, 'clip']).lower()

        # if the clipped tile doesn't exist yet, create it
        if not pg_util.check_table_exists(tile.postgis_table):

            # any TSV name will have the data as it's layer, otherwise use the actual shape
            file_ext = os.path.splitext(tile.dataset)[1]

            # why VRT here? so we can read the TSVs that are already created
            # which requires a crazy vector VRT file
            if file_ext in ['.tsv', '.vrt']:

                sql = "SELECT {}, GEOMETRY FROM data".format(col_str)

                cmd = ['ogr2ogr', '-f', 'PostgreSQL', conn_str, tile.dataset, '-nln', tile.postgis_table,
                       '-nlt', 'GEOMETRY', '-dialect', 'sqlite', '-sql', sql, '-lco', 'geometry_name=geom',
                       '-overwrite', '-s_srs', 'EPSG:4326', '-t_srs', 'EPSG:4326', '-dim', '2',
                       '-lco', 'SPATIAL_INDEX=NO']

                if tile.bbox:
                    bbox_list = [str(x) for x in tile.bbox]
                    cmd += ['-clipsrc'] + bbox_list

                    logging.info(cmd)

	        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    	        for line in iter(p.stdout.readline, b''):
		     if 'error' in line.lower():
		         logging.error('Error in loading dataset, {}'.format(cmd))

            # source dataset is already in postgis
            else:
                conn, cursor = pg_util.conn_to_postgis()

                # if it's a raster, already clipped to a tile and imported
                if not pg_util.is_raster(tile.postgis_table, cursor):

                    envelope = 'ST_MakeEnvelope({}, {}, {}, {}, 4326)'.format(*tile.bbox)

                    clip_sql = ('CREATE TABLE {n} AS '
                                'SELECT {c}, ST_Intersection(geom, {e}) as geom '
                                'FROM {t} '
                                'WHERE ST_Intersects(geom, {e})'.format(n=tile.postgis_table, c=col_str, t=tile.dataset, e=envelope))
                    logging.info(clip_sql)
                    cursor.execute(clip_sql)
                    conn.commit()
                conn.close()

            conn, cursor = pg_util.conn_to_postgis()

            # a few other things required to get our raster data to match vector
            if file_ext in ['.rvrt', '.tif']:
                pg_util.fix_raster_geom(tile.postgis_table, cursor)
            else:
                pg_util.fix_geom(tile.postgis_table, cursor, add_pkey=False)

            conn.commit()
            conn.close()

        q.task_done()
コード例 #6
0
def intersect(q):
    # source: https://pymotw.com/2/Queue/
    while True:
        output_layer, tile1, tile2 = q.get()

        conn, cursor = pg_util.conn_to_postgis()

        table_name = '{}_{}'.format(tile1.postgis_table, tile2.postgis_table)

        if pg_util.table_has_rows(cursor, tile1.postgis_table):

            # find which table has ISO/ID_1/ID_2 columns
            # will return ['a.ISO', 'a.ID_1', 'a._ID_2'] or b., depending on if first or second tile has admin columns
            admin2_columns = pg_util.find_admin_columns(cursor, tile1, tile2)

            # tile1 and tile2 could have same column names (bound1, bound2)
            # need to alias them to ensure that they're referenced properly
            tile1_cols = tile1.alias_select_columns('a')
            tile2_cols = tile2.alias_select_columns('b')

            tile_cols_aliased = []

            # rename boundary fields
            for i, fieldname in enumerate(tile1_cols + tile2_cols):
                tile_cols_aliased.append(fieldname + ' AS bound{}'.format(str(i)))

            select_cols = ", ".join(tile_cols_aliased + admin2_columns)
            groupby_columns = ", ".join(tile1_cols + tile2_cols + admin2_columns)

            # source: http://postgis.net/2014/03/14/tip_intersection_faster/
            sql = ("CREATE TABLE {table_name} AS "
                   "SELECT {s}, CASE "
                   " WHEN ST_CoveredBy(a.geom, b.geom) "
                   " THEN a.geom "
                   " ELSE ST_Intersection(a.geom, b.geom) "
                   " END as geom "
                   "FROM {table1} a "
                   "INNER JOIN {table2} b "
                   "ON ST_Intersects(a.geom, b.geom) ".format(s=select_cols, table_name=table_name,
                       table1=tile1.postgis_table, table2=tile2.postgis_table, g=groupby_columns))

            logging.info(sql)

            valid_intersect = True

            try:
                cursor.execute(sql)
                logging.info('Intersect for {} successful'.format(table_name))
            except Exception, e:
                valid_intersect = False
                logging.error('Error {} in sql statement {}'.format(sql, e))

            if valid_intersect:

                pg_util.fix_geom(table_name, cursor)

                if pg_util.table_has_rows(cursor, table_name):
                    output_tile = tile.Tile(None, None, tile1.tile_id, tile1.bbox, table_name)
                    output_layer.tile_list.append(output_tile)

        conn.commit()
        conn.close()

        q.task_done()