Example #1
0
def convert_tif_to_wgs84(input, output):
  '''convert from input to output to wgs84 CRS'''
  print(f'convert| {input}\n\t->{output}')

  dst_crs = 'EPSG:4326'
  with rio_open(input) as src:
    transform, width, height = calculate_default_transform(
        src.crs, dst_crs, src.width, src.height, *src.bounds)
    kwargs = src.meta.copy()
    kwargs.update({
        'crs': dst_crs,
        'transform': transform,
        'width': width,
        'height': height
    })

    with rio_open(output, 'w', **kwargs) as dst:
      for i in range(1, src.count + 1):
        reproject(
            source=band(src, i),
            destination=band(dst, i),
            src_transform=src.transform,
            src_crs=src.crs,
            dst_transform=transform,
            dst_crs=dst_crs,
            resampling=Resampling.nearest)
Example #2
0
def mosaic(images_paths):
    output = images_paths[0].replace('part0-', '')
    files_to_mosaic = [rio_open(path) for path in images_paths]
    mosaic, out_trans = merge(files_to_mosaic)
    out_profile = files_to_mosaic[0].profile.copy()
    out_profile.update({"height": mosaic.shape[1], "width": mosaic.shape[2], "transform": out_trans})
    with rio_open(output, 'w', **out_profile) as dataset:
        dataset.write(mosaic)

    for path, file in zip(images_paths, files_to_mosaic):
        file.close()
        os.remove(path)
Example #3
0
def mosaic(images_paths, delete=True):
    output = images_paths[0].replace('part0-', '')
    files_to_mosaic = [rio_open(path) for path in images_paths]
    mosaic, out_trans = merge(files_to_mosaic)
    out_profile = files_to_mosaic[0].profile.copy()
    out_profile.update({
        "height": mosaic.shape[1],
        "width": mosaic.shape[2],
        "transform": out_trans
    })
    print('preparing to write mosaic')
    with rio_open(output, 'w', **out_profile) as dataset:
        dataset.write(mosaic)
    print(f'mosaic created in: {output}')

    if delete:
        for path, file in zip(images_paths, files_to_mosaic):
            file.close()
            os.remove(path)
        print('Temporary files deleted')
def outputFiles(crs, masks):
    """
	* Output illustrative GIS (Shapefile and GeoTiff) files of the extracted
	*  zones and the aoi polygons
	"""

    # create the file in write mode, with the required CRS (Proj4 string) and an empty schema
    with fi_open('./tmp/aoi.shp',
                 'w',
                 driver='ESRI Shapefile',
                 crs=crs,
                 schema={
                     'geometry': 'Polygon',
                     'properties': {}
                 }) as o:

        # loop through resulting masks
        for m in range(len(masks)):

            # write the splitter to shapefile
            o.write({'geometry': mapping(masks[m]["aoi"]), 'properties': {}})

            # create a raster file
            with rio_open(
                    f'./tmp/{m}.tif',
                    'w',
                    driver=masks[m]["meta"]["driver"],
                    height=masks[m]["meta"]["height"],
                    width=masks[m]["meta"]["width"],
                    count=masks[m]["meta"]["count"],
                    dtype=masks[m]["meta"]["dtype"],
                    crs=masks[m]["meta"]["crs"],
                    transform=masks[m]["meta"]["transform"],
            ) as dst:

                # write the data to the raster
                dst.write(masks[m]["dtm"], 1)
Example #5
0
def concat(filenames,
           stack_dim='time',
           bounds_by='reference',
           resampling='nearest',
           time_names=None,
           band_names=None,
           nodata=None,
           dtype=None,
           overlap='max',
           warp_mem_limit=512,
           num_threads=1,
           tap=False,
           **kwargs):
    """
    Concatenates a list of images

    Args:
        filenames (list): A list of file names to concatenate.
        stack_dim (Optional[str]): The stack dimension. Choices are ['time', 'band'].
        bounds_by (Optional[str]): How to concatenate the output extent. Choices are ['intersection', 'union', 'reference'].

            * reference: Use the bounds of the reference image
            * intersection: Use the intersection (i.e., minimum extent) of all the image bounds
            * union: Use the union (i.e., maximum extent) of all the image bounds

        resampling (Optional[str]): The resampling method.
        time_names (Optional[1d array-like]): A list of names to give the time dimension.
        band_names (Optional[1d array-like]): A list of names to give the band dimension.
        nodata (Optional[float | int]): A 'no data' value to set. Default is None.
        dtype (Optional[str]): A data type to force the output to. If not given, the data type is extracted
            from the file.
        overlap (Optional[str]): The keyword that determines how to handle overlapping data.
            Choices are ['min', 'max', 'mean']. Only used when mosaicking arrays from the same timeframe.
        warp_mem_limit (Optional[int]): The memory limit (in MB) for the ``rasterio.vrt.WarpedVRT`` function.
        num_threads (Optional[int]): The number of warp worker threads.
        tap (Optional[bool]): Whether to target align pixels.
        kwargs (Optional[dict]): Keyword arguments passed to ``xarray.open_rasterio``.

    Returns:
        ``xarray.DataArray``
    """

    if stack_dim.lower() not in ['band', 'time']:
        logger.exception("  The stack dimension should be 'band' or 'time'")

    ref_kwargs = {
        'bounds': None,
        'crs': None,
        'res': None,
        'nodata': nodata,
        'warp_mem_limit': warp_mem_limit,
        'num_threads': num_threads,
        'tap': tap,
        'tac': None
    }

    ref_kwargs = _check_config_globals(filenames, bounds_by, ref_kwargs)

    with rio_open(filenames[0]) as src_:
        tags = src_.tags()

    # Keep a copy of the transformed attributes.
    with xr.open_rasterio(
            warp(filenames[0], resampling=resampling, **ref_kwargs),
            **kwargs) as src_:

        attrs = src_.attrs.copy()

    if time_names:

        concat_list = list()
        new_time_names = list()

        # Check the time names for duplicates
        for tidx in range(0, len(time_names)):

            if list(time_names).count(time_names[tidx]) > 1:

                if time_names[tidx] not in new_time_names:

                    # Get the file names to mosaic
                    filenames_mosaic = [
                        filenames[i] for i in range(0, len(time_names))
                        if time_names[i] == time_names[tidx]
                    ]

                    # Mosaic the images into a single-date array
                    concat_list.append(
                        mosaic(filenames_mosaic,
                               overlap=overlap,
                               bounds_by=bounds_by,
                               resampling=resampling,
                               band_names=band_names,
                               nodata=nodata,
                               warp_mem_limit=warp_mem_limit,
                               num_threads=num_threads,
                               **kwargs))

                    new_time_names.append(time_names[tidx])

            else:

                new_time_names.append(time_names[tidx])

                # Warp the date
                concat_list.append(
                    warp_open(filenames[tidx],
                              resampling=resampling,
                              band_names=band_names,
                              nodata=nodata,
                              warp_mem_limit=warp_mem_limit,
                              num_threads=num_threads,
                              **kwargs))

        # Warp all images and concatenate along the 'time' axis into a DataArray
        output = xr.concat(concat_list, dim=stack_dim.lower())

        # Assign the new time band names
        src = output.assign_coords(time=new_time_names)

    else:

        # Warp all images and concatenate along
        #   the 'time' axis into a DataArray.
        src = xr.concat([
            xr.open_rasterio(warp(fn, resampling=resampling, **ref_kwargs), **
                             kwargs) for fn in filenames
        ],
                        dim=stack_dim.lower())

    src.attrs['filename'] = [Path(fn).name for fn in filenames]

    if tags:
        attrs = src.attrs.copy()
        attrs.update(tags)

    src = src.assign_attrs(**attrs)

    if not time_names and (stack_dim == 'time'):
        src.coords['time'] = parse_filename_dates(filenames)

    if band_names:
        src.coords['band'] = band_names
    else:

        if src.gw.sensor:

            if src.gw.sensor not in src.gw.avail_sensors:

                logger.warning(
                    '  The {} sensor is not currently supported.\nChoose from [{}].'
                    .format(src.gw.sensor, ', '.join(src.gw.avail_sensors)))

            else:

                new_band_names = list(
                    src.gw.wavelengths[src.gw.sensor]._fields)

                if len(new_band_names) != len(src.band.values.tolist()):

                    if not src.gw.config['ignore_warnings']:

                        logger.warning(
                            '  The new bands, {}, do not match the sensor bands, {}.'
                            .format(new_band_names, src.band.values.tolist()))

                else:

                    src.coords['band'] = new_band_names
                    src.attrs['sensor'] = src.gw.sensor_names[src.gw.sensor]

    if dtype:

        attrs = src.attrs.copy()
        return src.astype(dtype).assign_attrs(**attrs)

    else:
        return src
Example #6
0
def mosaic(filenames,
           overlap='max',
           bounds_by='reference',
           resampling='nearest',
           band_names=None,
           nodata=None,
           dtype=None,
           warp_mem_limit=512,
           num_threads=1,
           **kwargs):
    """
    Mosaics a list of images

    Args:
        filenames (list): A list of file names to mosaic.
        overlap (Optional[str]): The keyword that determines how to handle overlapping data.
            Choices are ['min', 'max', 'mean'].
        bounds_by (Optional[str]): How to concatenate the output extent. Choices are ['intersection', 'union', 'reference'].

            * reference: Use the bounds of the reference image
            * intersection: Use the intersection (i.e., minimum extent) of all the image bounds
            * union: Use the union (i.e., maximum extent) of all the image bounds

        resampling (Optional[str]): The resampling method.
        band_names (Optional[1d array-like]): A list of names to give the band dimension.
        nodata (Optional[float | int]): A 'no data' value to set. Default is None.
        dtype (Optional[str]): A data type to force the output to. If not given, the data type is extracted
            from the file.
        warp_mem_limit (Optional[int]): The memory limit (in MB) for the ``rasterio.vrt.WarpedVRT`` function.
        num_threads (Optional[int]): The number of warp worker threads.
        kwargs (Optional[dict]): Keyword arguments passed to ``xarray.open_rasterio``.

    Returns:
        ``xarray.DataArray``
    """

    if overlap not in ['min', 'max', 'mean']:
        logger.exception(
            "  The overlap argument must be one of ['min', 'max', 'mean'].")

    ref_kwargs = {
        'bounds': None,
        'crs': None,
        'res': None,
        'nodata': nodata,
        'warp_mem_limit': warp_mem_limit,
        'num_threads': num_threads,
        'tac': None
    }

    ref_kwargs = _check_config_globals(filenames, bounds_by, ref_kwargs)

    # Warp all images to the same grid.
    warped_objects = warp_images(filenames,
                                 bounds_by=bounds_by,
                                 resampling=resampling,
                                 **ref_kwargs)

    footprints = []

    with rio_open(filenames[0]) as src_:
        tags = src_.tags()

    # Combine the data
    with xr.open_rasterio(warped_objects[0], **kwargs) as darray:

        attrs = darray.attrs.copy()

        # Get the original bounds, unsampled
        with xr.open_rasterio(filenames[0], **kwargs) as src_:
            footprints.append(src_.gw.geometry)

        for fidx, fn in enumerate(warped_objects[1:]):

            with xr.open_rasterio(fn, **kwargs) as darrayb:

                with xr.open_rasterio(filenames[fidx + 1], **kwargs) as src_:
                    footprints.append(src_.gw.geometry)
                src_ = None

                if overlap == 'min':

                    if isinstance(nodata, float) or isinstance(nodata, int):

                        darray = xr.where(
                            (darray.mean(dim='band') == nodata) &
                            (darrayb.mean(dim='band') != nodata), darrayb,
                            xr.where((darray.mean(dim='band') != nodata) &
                                     (darrayb.mean(dim='band') == nodata),
                                     darray, xr_mininum(darray, darrayb)))

                    else:
                        darray = xr_mininum(darray, darrayb)

                elif overlap == 'max':

                    if isinstance(nodata, float) or isinstance(nodata, int):

                        darray = xr.where(
                            (darray.mean(dim='band') == nodata) &
                            (darrayb.mean(dim='band') != nodata), darrayb,
                            xr.where((darray.mean(dim='band') != nodata) &
                                     (darrayb.mean(dim='band') == nodata),
                                     darray, xr_maximum(darray, darrayb)))

                    else:
                        darray = xr_maximum(darray, darrayb)

                elif overlap == 'mean':

                    if isinstance(nodata, float) or isinstance(nodata, int):

                        darray = xr.where(
                            (darray.mean(dim='band') == nodata) &
                            (darrayb.mean(dim='band') != nodata), darrayb,
                            xr.where((darray.mean(dim='band') != nodata) &
                                     (darrayb.mean(dim='band') == nodata),
                                     darray, (darray + darrayb) / 2.0))

                    else:
                        darray = (darray + darrayb) / 2.0

                # darray = darray.combine_first(darrayb)

        darray = darray.assign_attrs(**attrs)

        if band_names:
            darray.coords['band'] = band_names
        else:

            if darray.gw.sensor:

                if darray.gw.sensor not in darray.gw.avail_sensors:

                    logger.warning(
                        '  The {} sensor is not currently supported.\nChoose from [{}].'
                        .format(darray.gw.sensor,
                                ', '.join(darray.gw.avail_sensors)))

                else:

                    new_band_names = list(
                        darray.gw.wavelengths[darray.gw.sensor]._fields)

                    if len(new_band_names) != len(darray.band.values.tolist()):
                        logger.warning(
                            '  The band list length does not match the sensor bands.'
                        )
                    else:

                        darray.coords['band'] = new_band_names
                        darray.attrs['sensor'] = darray.gw.sensor_names[
                            darray.gw.sensor]

        darray.attrs['filename'] = [Path(fn).name for fn in filenames]
        darray.attrs['resampling'] = resampling

        if tags:
            attrs = darray.attrs.copy()
            attrs.update(tags)
            darray = darray.assign_attrs(**attrs)

        darray.gw.footprint_grid = footprints

        if dtype:

            attrs = darray.attrs.copy()
            return darray.astype(dtype).assign_attrs(**attrs)

        else:
            return darray
Example #7
0
def warp_open(filename,
              band_names=None,
              nodata=None,
              resampling='nearest',
              dtype=None,
              return_windows=False,
              warp_mem_limit=512,
              num_threads=1,
              tap=False,
              **kwargs):
    """
    Warps and opens a file

    Args:
        filename (str): The file to open.
        band_names (Optional[int, str, or list]): The band names.
        nodata (Optional[float | int]): A 'no data' value to set. Default is None.
        resampling (Optional[str]): The resampling method.
        dtype (Optional[str]): A data type to force the output to. If not given, the data type is extracted
            from the file.
        return_windows (Optional[bool]): Whether to return block windows.
        warp_mem_limit (Optional[int]): The memory limit (in MB) for the ``rasterio.vrt.WarpedVRT`` function.
        num_threads (Optional[int]): The number of warp worker threads.
        tap (Optional[bool]): Whether to target align pixels.
        kwargs (Optional[dict]): Keyword arguments passed to ``xarray.open_rasterio``.

    Returns:
        ``xarray.DataArray``
    """

    ref_kwargs = {
        'bounds': None,
        'crs': None,
        'res': None,
        'nodata': nodata,
        'warp_mem_limit': warp_mem_limit,
        'num_threads': num_threads,
        'tap': tap,
        'tac': None
    }

    ref_kwargs = _check_config_globals(filename, 'reference', ref_kwargs)

    with rio_open(filename) as src:
        tags = src.tags()

    with xr.open_rasterio(warp(filename, resampling=resampling, **ref_kwargs),
                          **kwargs) as src:

        if band_names:
            src.coords['band'] = band_names
        else:

            if src.gw.sensor:

                if src.gw.sensor not in src.gw.avail_sensors:

                    logger.warning(
                        '  The {} sensor is not currently supported.\nChoose from [{}].'
                        .format(src.gw.sensor,
                                ', '.join(src.gw.avail_sensors)))

                else:

                    new_band_names = list(
                        src.gw.wavelengths[src.gw.sensor]._fields)

                    # Avoid nested opens within a `config` context
                    if len(new_band_names) != len(src.band.values.tolist()):

                        if not src.gw.config['ignore_warnings']:

                            logger.warning(
                                '  The new bands, {}, do not match the sensor bands, {}.'
                                .format(new_band_names,
                                        src.band.values.tolist()))

                    else:

                        src.coords['band'] = new_band_names
                        src.attrs['sensor'] = src.gw.sensor_names[
                            src.gw.sensor]

        if return_windows:

            if isinstance(kwargs['chunks'], tuple):
                chunksize = kwargs['chunks'][-1]
            else:
                chunksize = kwargs['chunks']

            src.attrs['block_windows'] = get_window_offsets(src.shape[-2],
                                                            src.shape[-1],
                                                            chunksize,
                                                            chunksize,
                                                            return_as='list')

        src.attrs['filename'] = filename
        src.attrs['resampling'] = resampling

        if tags:
            attrs = src.attrs.copy()
            attrs.update(tags)
            src = src.assign_attrs(**attrs)

        if dtype:

            attrs = src.attrs.copy()
            return src.astype(dtype).assign_attrs(**attrs)

        else:
            return src
def f(mask, aoi_id, plot=False):
    '''
	* run parallel process
	'''

    # turn off pymc3 logging
    getLogger("pymc3").setLevel(ERROR)

    # get transform object for the dataset (nw corner & resolution)
    transform = from_origin(mask['bounds'][0], mask['bounds'][3],
                            mask['resolution'], mask['resolution'])

    # check that output directory is there
    if not exists("./out/"):
        makedirs("./out/")

    # seed data and uncertainty arrays for the study area and build dictionary to control outputs
    c_data = zeros(
        (ceil((mask['bounds'][3] - mask['bounds'][1]) / mask['resolution']),
         ceil((mask['bounds'][2] - mask['bounds'][0]) / mask['resolution'])))
    outputs = {
        'catholic': {
            'path': f'./out/{aoi_id}_catholic.tif',
            'mean': c_data,
            'low': c_data.copy(),
            'high': c_data.copy()
        },
        'protestant': {
            'path': f'./out/{aoi_id}_protestant.tif',
            'mean': c_data.copy(),
            'low': c_data.copy(),
            'high': c_data.copy()
        },
        'mixed': {
            'path': f'./out/{aoi_id}_mixed.tif',
            'mean': c_data.copy(),
            'low': c_data.copy(),
            'high': c_data.copy()
        }
    }

    # extract list of group names
    groups = array(list(outputs.keys()))

    # use try-finally so if it fails we can see where it got up to
    # try:

    print(f"AOI Dimensions: {c_data.shape[1]}x{c_data.shape[0]}px")

    # loop through rows and columns in the dataset
    for row in range(c_data.shape[0]):
        for col in range(c_data.shape[1]):

            print(
                f"\t...{row * c_data.shape[1] + col} of {c_data.shape[0] * c_data.shape[1]} ({(row * c_data.shape[1] + col)/(c_data.shape[0] * c_data.shape[1])*100:.2f}%)"
            )

            # get coordinates for the point
            point = Point(array2Coords(transform, row, col))
            ''' calculate hyperparameters (priors) '''

            # get the census data for the census Small Area that contains the point
            possible_matches = mask['census'].iloc[list(
                mask['census'].sindex.intersection(point.bounds))]
            district = possible_matches.loc[possible_matches.contains(point)][[
                'pcCatholic', 'pcProtesta', 'pc_Other', 'pc_None'
            ]]

            # make sure that there was a match at all!
            if len(district.index) > 0:

                # compute proportions for the three groups
                # replace zeros for 1s as you are not allowed 0's in the hyperparameters (gives Bad initial energy error)
                alphas = maximum(
                    ones(3),
                    array([
                        int(round(district['pcCatholic'].iloc[0])),
                        int(round(district['pcProtesta'].iloc[0])),
                        int(
                            round(district['pc_Other'].iloc[0] +
                                  district['pc_None'].iloc[0]))
                    ]))

            else:
                # if no matches, have equal belief for each group
                alphas = array([1, 1, 1])
            ''' calculate observations '''

            # init lists for observations
            c = []
            n = []

            # construct the radius for analysis
            polygon = point.buffer(mask['radius'])

            # loop through each dataset
            for i, gdf in mask['datasets'].items():

                # check that there is data available (this is if no data has been
                #  passed in the mask as the clip polygon does not intersect any)
                if len(gdf.index) > 0:

                    # get data points within and get IDW2 multiplier
                    possible_matches = gdf.iloc[list(
                        gdf.sindex.intersection(polygon.bounds))]
                    observations = possible_matches.loc[
                        possible_matches.within(polygon)]

                    observations['idw2'] = (
                        1 - observations.geometry.distance(point) /
                        mask['radius'])**2

                    # check that there is data available (this is if data has been
                    #  passed but the buffer polygon does not intersect it)
                    if len(observations) > 0:

                        # get weighted group counts for the current dataset
                        if i == 'mapme':
                            catholics, protestants, mixed = getMapmeGroups(
                                observations)
                        elif i == 'gps':
                            catholics, protestants, mixed = getGpsGroups(
                                observations)
                        elif i == 'survey':
                            catholics, protestants, mixed = getSurveyGroups(
                                observations)

                        # index and int the scores for each dataset
                        sums = [catholics, protestants, mixed]

                        # catch error caused by no probabilities
                        if sum(sums) > 0:

                            print(sums)

                            # process into correct format
                            sums = [
                                int(round(i / sum(sums) * 100)) for i in sums
                            ]

                            # append to observations list
                            c.append(sums)
                            n.append(sum(sums))

                            # TODO: DO I WANT ALL THESE 0'S OR ARE THEY GOING TO CAUSE PROBLEMS?

                        else:
                            # if not matches, just append some empty data
                            c.append([0, 0, 0])
                            n.append(0)
                    else:
                        # if not matches, just append some empty data
                        c.append([0, 0, 0])
                        n.append(0)
                else:
                    # if not matches, just append some empty data
                    c.append([0, 0, 0])
                    n.append(0)

            # convert observations np array
            c = array(c)
            n = array(n)

            # print(alphas, c, n)
            # print()
            ''' run model '''

            # start making MCC model
            with Model() as model:

                # TODO: LOOK INTO TESTVALS FOR PARAMETERS
                # https://nbviewer.jupyter.org/github/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/blob/master/Chapter3_MCMC/Ch3_IntroMCMC_PyMC3.ipynb#Intelligent-starting-values

                # parameters of the Multinomial are from a Dirichlet
                parameters = Dirichlet('parameters', a=alphas, shape=3)

                # observed data is from a Multinomial distribution
                observed_data = Multinomial('observed_data',
                                            n=n,
                                            p=parameters,
                                            shape=3,
                                            observed=c)

                with model:

                    # estimate the Maximum a Posterior
                    # start = find_MAP()	#don't use this - it prevents convergence!

                    # sample from the posterior (NUTS is default so is not explicitly stated)
                    trace = sample(
                        # start=start,                # start at the MAP to increase chance of convergence -- DON'T DO THIS!
                        draws=1000,  # number of sample draws
                        chains=
                        4,  # number of chains in which the above are drawn (match cores)
                        cores=1,  # max permitted by library
                        tune=500,  # how many will be discarded (>=50% of draws)
                        discard_tuned_samples=True,  # discard the tuning samples
                        progressbar=
                        False,  # avoid unnecessarilly filling up the output file
                        target_accept=
                        0.9  # up from 0.8 to avoid false positives: https://eigenfoo.xyz/bayesian-modelling-cookbook/#fixing-divergences
                    )

                    if plot:
                        plot_trace(trace, show=True)

                    # retrieve summary data
                    results = summary(trace)
                    results.index = groups

            # output the result to the datasets
            for k, v in outputs.items():
                v['mean'][row, col] = results.loc[k, 'mean']
                v['low'][row, col] = results.loc[k, 'hpd_3%']
                v['high'][row, col] = results.loc[k, 'hpd_97%']

    # if we get an error - print some debugging info
    # except Exception as e:
    #     print("\n--- EXCEPTION ---")
    #     print(e)
    #     print(row, col, point)
    #     if (sums):
    #         print(sums)
    #     else:
    #         print("sums not defined yet")
    #     print(c, n)
    #
    # # whatever happens, output the results to files
    # finally:

    # loop through outputs
    for g in outputs.values():

        # output dataset to raster (hardcoded crs as was causing error)
        with rio_open(g['path'],
                      'w',
                      driver='GTiff',
                      height=g['mean'].shape[0],
                      width=g['mean'].shape[1],
                      count=3,
                      dtype='float64',
                      crs="EPSG:29902",
                      transform=transform) as out:

            # add data and uncertainties as raster bands
            out.write(g['mean'], 1)
            out.write(g['low'], 2)
            out.write(g['high'], 3)
Example #9
0
from glob import glob
from rasterio import open as rio_open
from rasterio.merge import merge as rio_merge

# get all tif images in directory
images = glob('../CEF-Result/out/*.tif')

# get files
files = []
for file in images:
    files.append(rio_open(file, 'r'))

# merge result files
merged, out_transform = rio_merge(files, method='max')

# output dataset to raster (hardcoded crs as was causing error)
with rio_open("../CEF-Result/800m.tif", 'w', driver='GTiff', height=merged.shape[1],
    width=merged.shape[2], count=1, dtype='float64', crs="EPSG:27700",
    transform=out_transform) as out:

    out.write(merged[0], 1)

# close all of the files
for file in files:
    file.close()

print("done")
Example #10
0
    'set the name of the variable that contains the output JS object (default: \'data\')'
)
args = parser.parse_args()

# validate output file is JavaScript
if args.output[0][-3:] != ".js":
    print(
        "Sorry, " + args.output[0] +
        " is not a JavaScript file - it should be named in the form: \"*.js\"")
    exit()

# ready to catch errors
try:

    # open input data set
    with rio_open(args.input[0]) as ds:

        # open output file
        file = open(args.output[0], 'w')

        # get list of bands if specified, otherwise set to all bands
        if (args.bands):
            bands = [int(x) for x in args.bands]
        else:
            bands = list(range(1, ds.count + 1))

        # get projection string (from online if it is EPSG as proj4js doesn't like them)
        if ds.crs.is_epsg_code:
            projString = get("https://epsg.io/" + ds.crs.to_proj4()[11:] +
                             ".proj4").text
        else:
# log start time and log start
time = datetime.now()
print(
    f"a {sections[0]}x{sections[1]} grid, {sections[0]*sections[1]} processes, started at {time}."
)

# initialise masks array for the results
masks = []

# get aoi bounds from shapefile
with fi_open(boundary_path) as boundary:
    bounds = boundary.bounds

# read in raster data
with rio_open(dtm_path) as dtm_input:
    with rio_open(dsm_path) as dsm_input:
        with rio_open(green_path) as green_input:

            # verify raster dimensions and resolution
            if (dsm_input.width == dtm_input.width == green_input.width) == False or \
             (dsm_input.height == dtm_input.height == green_input.height) == False or \
             (dsm_input.res[0] == dtm_input.res[0] == green_input.res[0]) == False:
                print("rasters do not match!")
                print("width: \t\t",
                      dsm_input.width == dtm_input.width == green_input.width)
                print(
                    "height: \t",
                    dsm_input.height == dtm_input.height == green_input.height)
                print(
                    "resolution: \t",
Example #12
0
 def array(self):
     with rio_open(self.path, 'r') as dataset:
         return dataset.read(1)
Example #13
0
 def plot(self, **kwargs):
     with rio_open(self.path, 'r') as dataset:
         imshow(dataset.read(1), **kwargs)
def f(mask):
	"""
	* main function for running with parallel.py
	"""

	# create an output array at the same dimensions as data for output
	gvi = zeros((mask["meta"]["height"], mask["meta"]["width"]))

	# radius in pixels
	radius_px = int(mask["options"]["radius"] // mask['meta']['transform'][0])

	# build weighting mask
	weighting_mask = zeros((radius_px*2, radius_px*2))
	for r, c in column_stack(disk((radius_px, radius_px), radius_px, shape=weighting_mask.shape)):
		weighting_mask[(r, c)] = exp(-0.0003 * (hypot(radius_px - c, radius_px - r) * mask['meta']['transform'][0]))

	# get pixel references for aoi extents
	min_r, min_c  = coords2Array(mask["meta"]["transform"], mask["aoi"].bounds[0], mask["aoi"].bounds[3])
	max_r, max_c  = coords2Array(mask["meta"]["transform"], mask["aoi"].bounds[2], mask["aoi"].bounds[1])

	# loop through dataset rows and columns
	for r in range(min_r, max_r+1):
		for c in range(min_c, max_c+1):

			# print(r, c)
			# t1_start = perf_counter()

			# call (weighted) viewshed
			output = viewshed(r, c, radius_px, 		# coords and radius in pixels
				mask['meta']['transform'][0],		# resolution of datasets
				mask["options"]["o_height"], 		# observer height
				mask["options"]["t_height"],		# target height
				mask["dsm"], 						# dsm dataset
				mask["dtm"],						# dtm dataset
				mask["meta"]["transform"])			# affine transform

			# extract the viewshed data from the output surface and apply weighting mask
			visible = output[r-radius_px:r+radius_px, c-radius_px:c+radius_px] * weighting_mask

			# print(f"\tviewshed took {perf_counter() - t1_start}s", visible.shape, visible.sum())
			# t1_start = perf_counter()

			# multiply extract of (weighted) viewshed with extract of (weighted) green dataset
			visible_green = visible * (mask["green"][r-radius_px:r+radius_px, c-radius_px:c+radius_px] * weighting_mask)

			# print(f"\tvisible green {perf_counter() - t1_start}s", visible_green.shape, visible_green.sum())
			# t1_start = perf_counter()

			# get the ratio for greenness in the view
			gvi[(r,c)] = visible_green.sum() / visible.sum()

			# print(f"\tgvi took {perf_counter() - t1_start}s", gvi[(r,c)])
			# print()

	# clip gvi to aoi bounds
	gvi = gvi[min_r:max_r+1, min_c:max_c+1]

	# check that tmp folder exists
	if not exists('./tmp/'):
	    makedirs('tmp')

	# make unique filename
	filepath = f'./tmp/{str(uuid1())[:8]}.tif'

	# output file with updated dimensions and transform
	with rio_open(filepath, 'w',
		driver =	mask["meta"]["driver"],
		height = 	gvi.shape[0],
		width =		gvi.shape[1],
		count =		mask["meta"]["count"],
		dtype =		'float64',
		crs =		mask["meta"]["crs"],
		transform =	Affine(
			mask['meta']['transform'][0],
			mask['meta']['transform'][1],
			mask["aoi"].bounds[0],
			mask['meta']['transform'][3],
			mask['meta']['transform'][4],
			mask["aoi"].bounds[3]),
		) as dst:
		dst.write(gvi, 1)

	# return the filepath to the result
	return filepath
Example #15
0
def warp_open(filename,
              band_names=None,
              resampling='nearest',
              dtype=None,
              netcdf_vars=None,
              nodata=0,
              return_windows=False,
              warp_mem_limit=512,
              num_threads=1,
              tap=False,
              **kwargs):
    """
    Warps and opens a file

    Args:
        filename (str): The file to open.
        band_names (Optional[int, str, or list]): The band names.
        resampling (Optional[str]): The resampling method.
        dtype (Optional[str]): A data type to force the output to. If not given, the data type is extracted
            from the file.
        netcdf_vars (Optional[list]): NetCDF variables to open as a band stack.
        nodata (Optional[float | int]): A 'no data' value to set. Default is 0.
        return_windows (Optional[bool]): Whether to return block windows.
        warp_mem_limit (Optional[int]): The memory limit (in MB) for the ``rasterio.vrt.WarpedVRT`` function.
        num_threads (Optional[int]): The number of warp worker threads.
        tap (Optional[bool]): Whether to target align pixels.
        kwargs (Optional[dict]): Keyword arguments passed to ``xarray.open_rasterio``.

    Returns:
        ``xarray.DataArray``
    """

    ref_kwargs = {
        'bounds': None,
        'crs': None,
        'res': None,
        'nodata': nodata,
        'warp_mem_limit': warp_mem_limit,
        'num_threads': num_threads,
        'tap': tap,
        'tac': None
    }

    ref_kwargs_netcdf_stack = ref_kwargs.copy()
    ref_kwargs_netcdf_stack['bounds_by'] = 'union'
    del ref_kwargs_netcdf_stack['tap']

    ref_kwargs = _check_config_globals(filename, 'reference', ref_kwargs)

    filenames = None

    # Create a list of variables to open
    if filename.lower().startswith('netcdf:') and netcdf_vars:
        filenames = (f'{filename}:' +
                     f',{filename}:'.join(netcdf_vars)).split(',')

    if filenames:

        ref_kwargs_netcdf_stack = _check_config_globals(
            filenames[0], 'reference', ref_kwargs_netcdf_stack)

        with rio_open(filenames[0]) as src:
            tags = src.tags()

    else:

        ref_kwargs_netcdf_stack = _check_config_globals(
            filename, 'reference', ref_kwargs_netcdf_stack)

        with rio_open(filename) as src:
            tags = src.tags()

    @contextlib.contextmanager
    def warp_netcdf_vars():

        # Warp all images to the same grid.
        warped_objects = warp_images(filenames,
                                     resampling=resampling,
                                     **ref_kwargs_netcdf_stack)

        yield xr.concat((xr.open_rasterio(wobj, **kwargs)\
                            .assign_coords(band=[band_names[wi]] if band_names else [netcdf_vars[wi]])
                         for wi, wobj in enumerate(warped_objects)), dim='band')

    with xr.open_rasterio(
            warp(filename, resampling=resampling, **ref_kwargs), **
            kwargs) if not filenames else warp_netcdf_vars() as src:

        if band_names:

            if len(band_names) > src.gw.nbands:
                src.coords['band'] = band_names[:src.gw.nbands]
            else:
                src.coords['band'] = band_names

        else:

            if src.gw.sensor:

                if src.gw.sensor not in src.gw.avail_sensors:

                    if not src.gw.config['ignore_warnings']:

                        logger.warning(
                            '  The {} sensor is not currently supported.\nChoose from [{}].'
                            .format(src.gw.sensor,
                                    ', '.join(src.gw.avail_sensors)))

                else:

                    new_band_names = list(
                        src.gw.wavelengths[src.gw.sensor]._fields)

                    # Avoid nested opens within a `config` context
                    if len(new_band_names) != len(src.band.values.tolist()):

                        if not src.gw.config['ignore_warnings']:

                            logger.warning(
                                '  The new bands, {}, do not match the sensor bands, {}.'
                                .format(new_band_names,
                                        src.band.values.tolist()))

                    else:

                        src.coords['band'] = new_band_names
                        src.attrs['sensor'] = src.gw.sensor_names[
                            src.gw.sensor]

        if return_windows:

            if isinstance(kwargs['chunks'], tuple):
                chunksize = kwargs['chunks'][-1]
            else:
                chunksize = kwargs['chunks']

            src.attrs['block_windows'] = get_window_offsets(src.shape[-2],
                                                            src.shape[-1],
                                                            chunksize,
                                                            chunksize,
                                                            return_as='list')

        src.attrs['filename'] = filename
        src.attrs['resampling'] = resampling

        if tags:
            attrs = src.attrs.copy()
            attrs.update(tags)
            src = src.assign_attrs(**attrs)

        if dtype:

            attrs = src.attrs.copy()
            return src.astype(dtype).assign_attrs(**attrs)

        else:
            return src