Instruction:
Given the following Python 3 function, write the documentation
def get_raw_output(self, tile, _baselevel_readonly=False):
        if not isinstance(tile, (BufferedTile, tuple)):
            raise TypeError("'tile' must be a tuple or BufferedTile")
        if isinstance(tile, tuple):
            tile = self.config.output_pyramid.tile(*tile)
        if _baselevel_readonly:
            tile = self.config.baselevels["tile_pyramid"].tile(*tile.id)

        # Return empty data if zoom level is outside of process zoom levels.
        if tile.zoom not in self.config.zoom_levels:
            return self.config.output.empty(tile)

        # TODO implement reprojection
        if tile.crs != self.config.process_pyramid.crs:
            raise NotImplementedError(
                "reprojection between processes not yet implemented"
            )

        if self.config.mode == "memory":
            # Determine affected process Tile and check whether it is already
            # cached.
            process_tile = self.config.process_pyramid.intersecting(tile)[0]
            return self._extract(
                in_tile=process_tile,
                in_data=self._execute_using_cache(process_tile),
                out_tile=tile
            )

        # TODO: cases where tile intersects with multiple process tiles
        process_tile = self.config.process_pyramid.intersecting(tile)[0]

        # get output_tiles that intersect with current tile
        if tile.pixelbuffer > self.config.output.pixelbuffer:
            output_tiles = list(self.config.output_pyramid.tiles_from_bounds(
                tile.bounds, tile.zoom
            ))
        else:
            output_tiles = self.config.output_pyramid.intersecting(tile)

        if self.config.mode == "readonly" or _baselevel_readonly:
            if self.config.output.tiles_exist(process_tile):
                return self._read_existing_output(tile, output_tiles)
            else:
                return self.config.output.empty(tile)
        elif self.config.mode == "continue" and not _baselevel_readonly:
            if self.config.output.tiles_exist(process_tile):
                return self._read_existing_output(tile, output_tiles)
            else:
                return self._process_and_overwrite_output(tile, process_tile)
        elif self.config.mode == "overwrite" and not _baselevel_readonly:
            return self._process_and_overwrite_output(tile, process_tile)

Response: Get raw output data for a given tile.


Instruction:
Can you write a function in Python 3 where it
extracts data from tile.

Response:
def _extract(self, in_tile=None, in_data=None, out_tile=None):
        """Extract data from tile."""
        return self.config.output.extract_subset(
            input_data_tiles=[(in_tile, in_data)],
            out_tile=out_tile
        )


Instruction:
How would you explain what the following Python 3 function does
def read(self, **kwargs):
        if self.tile.pixelbuffer > self.config.output.pixelbuffer:
            output_tiles = list(self.config.output_pyramid.tiles_from_bounds(
                self.tile.bounds, self.tile.zoom
            ))
        else:
            output_tiles = self.config.output_pyramid.intersecting(self.tile)
        return self.config.output.extract_subset(
            input_data_tiles=[
                (output_tile, self.config.output.read(output_tile))
                for output_tile in output_tiles
            ],
            out_tile=self.tile,
        )

Response: Read existing output data from a previous run.


Instruction:
Here you have a function in Python 3, explain what it does
def open(self, input_id, **kwargs):
        if not isinstance(input_id, str):
            return input_id.open(self.tile, **kwargs)
        if input_id not in self.params["input"]:
            raise ValueError("%s not found in config as input file" % input_id)
        return self.params["input"][input_id].open(self.tile, **kwargs)

Response:
Open input data.

        Parameters
        ----------
        input_id : string
            input identifier from configuration file or file path
        kwargs : driver specific parameters (e.g. resampling)

        Returns
        -------
        tiled input data : InputTile
            reprojected input data within tile


Instruction:
How would you code a function in Python 3 to
calculate hillshading from elevation data.

Response:
def hillshade(
        self, elevation, azimuth=315.0, altitude=45.0, z=1.0, scale=1.0
    ):
        """
        Calculate hillshading from elevation data.

        Parameters
        ----------
        elevation : array
            input elevation data
        azimuth : float
            horizontal angle of light source (315: North-West)
        altitude : float
            vertical angle of light source (90 would result in slope shading)
        z : float
            vertical exaggeration factor
        scale : float
            scale factor of pixel size units versus height units (insert 112000
            when having elevation values in meters in a geodetic projection)

        Returns
        -------
        hillshade : array
        """
        return commons_hillshade.hillshade(
            elevation, self, azimuth, altitude, z, scale)


Instruction:
Create a Python 3 function for
returning a list of contour lines from the elevation data.

Response:
def contours(
        self, elevation, interval=100, field='elev', base=0
    ):
        """
        Extract contour lines from elevation data.

        Parameters
        ----------
        elevation : array
            input elevation data
        interval : integer
            elevation value interval when drawing contour lines
        field : string
            output field name containing elevation value
        base : integer
            elevation base value the intervals are computed from

        Returns
        -------
        contours : iterable
            contours as GeoJSON-like pairs of properties and geometry
        """
        return commons_contours.extract_contours(
            elevation, self.tile, interval=interval, field=field, base=base)


Instruction:
Write a Python 3 function for
clipping array by geometry.

Response:
def clip(
        self, array, geometries, inverted=False, clip_buffer=0
    ):
        """
        Clip array by geometry.

        Parameters
        ----------
        array : array
            raster data to be clipped
        geometries : iterable
            geometries used to clip source array
        inverted : bool
            invert clipping (default: False)
        clip_buffer : int
            buffer (in pixels) geometries before applying clip

        Returns
        -------
        clipped array : array
        """
        return commons_clip.clip_array_with_vector(
            array, self.tile.affine, geometries,
            inverted=inverted, clip_buffer=clip_buffer*self.tile.pixel_x_size)


Instruction:
Here you have a function in Python 3, explain what it does
def clip_array_with_vector(
    array, array_affine, geometries, inverted=False, clip_buffer=0
):
    """
    Clip input array with a vector list.

    Parameters
    ----------
    array : array
        input raster data
    array_affine : Affine
        Affine object describing the raster's geolocation
    geometries : iterable
        iterable of dictionaries, where every entry has a 'geometry' and
        'properties' key.
    inverted : bool
        invert clip (default: False)
    clip_buffer : integer
        buffer (in pixels) geometries before clipping

    Returns
    -------
    clipped array : array
    """
    # buffer input geometries and clean up
    buffered_geometries = []
    for feature in geometries:
        feature_geom = to_shape(feature["geometry"])
        if feature_geom.is_empty:
            continue
        if feature_geom.geom_type == "GeometryCollection":
            # for GeometryCollections apply buffer to every subgeometry
            # and make union
            buffered_geom = unary_union([
                g.buffer(clip_buffer) for g in feature_geom])
        else:
            buffered_geom = feature_geom.buffer(clip_buffer)
        if not buffered_geom.is_empty:
            buffered_geometries.append(buffered_geom)

    # mask raster by buffered geometries
    if buffered_geometries:
        if array.ndim == 2:
            return ma.masked_array(
                array, geometry_mask(
                    buffered_geometries, array.shape, array_affine,
                    invert=inverted))
        elif array.ndim == 3:
            mask = geometry_mask(
                buffered_geometries, (array.shape[1], array.shape[2]),
                array_affine, invert=inverted)
            return ma.masked_array(
                array, mask=np.stack((mask for band in array)))

    # if no geometries, return unmasked array
    else:
        fill = False if inverted else True
        return ma.masked_array(
            array, mask=np.full(array.shape, fill, dtype=bool))

Response: Clip input array with a vector list.


Instruction:
Write a Python 3 function that can
create tile pyramid out of input raster.

Response:
def pyramid(
    input_raster,
    output_dir,
    pyramid_type=None,
    output_format=None,
    resampling_method=None,
    scale_method=None,
    zoom=None,
    bounds=None,
    overwrite=False,
    debug=False
):
    """Create tile pyramid out of input raster."""
    bounds = bounds if bounds else None
    options = dict(
        pyramid_type=pyramid_type,
        scale_method=scale_method,
        output_format=output_format,
        resampling=resampling_method,
        zoom=zoom,
        bounds=bounds,
        overwrite=overwrite
    )
    raster2pyramid(input_raster, output_dir, options)


Instruction:
Can you create a Python 3 function that
creates a tile pyramid from an input raster dataset.

Response:
def raster2pyramid(input_file, output_dir, options):
    """Create a tile pyramid out of an input raster dataset."""
    pyramid_type = options["pyramid_type"]
    scale_method = options["scale_method"]
    output_format = options["output_format"]
    resampling = options["resampling"]
    zoom = options["zoom"]
    bounds = options["bounds"]
    mode = "overwrite" if options["overwrite"] else "continue"

    # Prepare process parameters
    minzoom, maxzoom = _get_zoom(zoom, input_file, pyramid_type)
    with rasterio.open(input_file, "r") as input_raster:
        output_bands = input_raster.count
        input_dtype = input_raster.dtypes[0]
        output_dtype = input_raster.dtypes[0]
        nodataval = input_raster.nodatavals[0]
        nodataval = nodataval if nodataval else 0
        if output_format == "PNG" and output_bands > 3:
            output_bands = 3
            output_dtype = 'uint8'
        scales_minmax = ()
        if scale_method == "dtype_scale":
            for index in range(1, output_bands+1):
                scales_minmax += (DTYPE_RANGES[input_dtype], )
        elif scale_method == "minmax_scale":
            for index in range(1, output_bands+1):
                band = input_raster.read(index)
                scales_minmax += ((band.min(), band.max()), )
        elif scale_method == "crop":
            for index in range(1, output_bands+1):
                scales_minmax += ((0, 255), )
        if input_dtype == "uint8":
            scale_method = None
            scales_minmax = ()
            for index in range(1, output_bands+1):
                scales_minmax += ((None, None), )

    # Create configuration
    config = dict(
        process="mapchete.processes.pyramid.tilify",
        output={
            "path": output_dir,
            "format": output_format,
            "bands": output_bands,
            "dtype": output_dtype
            },
        pyramid=dict(pixelbuffer=5, grid=pyramid_type),
        scale_method=scale_method,
        scales_minmax=scales_minmax,
        input={"raster": input_file},
        config_dir=os.getcwd(),
        zoom_levels=dict(min=minzoom, max=maxzoom),
        nodataval=nodataval,
        resampling=resampling,
        bounds=bounds,
        baselevel={"zoom": maxzoom, "resampling": resampling},
        mode=mode
    )

    # create process
    with mapchete.open(config, zoom=zoom, bounds=bounds) as mp:
        # prepare output directory
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        # run process
        mp.batch_process(zoom=[minzoom, maxzoom])


Instruction:
Write a Python 3 script for
determining minimum and maximum zoomlevel.

Response:
def _get_zoom(zoom, input_raster, pyramid_type):
    """Determine minimum and maximum zoomlevel."""
    if not zoom:
        minzoom = 1
        maxzoom = get_best_zoom_level(input_raster, pyramid_type)
    elif len(zoom) == 1:
        minzoom = zoom[0]
        maxzoom = zoom[0]
    elif len(zoom) == 2:
        if zoom[0] < zoom[1]:
            minzoom = zoom[0]
            maxzoom = zoom[1]
        else:
            minzoom = zoom[1]
            maxzoom = zoom[0]
    return minzoom, maxzoom


Instruction:
Can you tell what is the following Python 3 function doing
def validate_values(config, values):
    if not isinstance(config, dict):
        raise TypeError("config must be a dictionary")
    for value, vtype in values:
        if value not in config:
            raise ValueError("%s not given" % value)
        if not isinstance(config[value], vtype):
            raise TypeError("%s must be %s" % (value, vtype))
    return True

Response: Validate whether values are found in config and has the right type.


Instruction:
Can you create a Python 3 function that
returns hash of x.

Response:
def get_hash(x):
    """Return hash of x."""
    if isinstance(x, str):
        return hash(x)
    elif isinstance(x, dict):
        return hash(yaml.dump(x))


Instruction:
How would you explain what the following Python 3 function does
def get_zoom_levels(process_zoom_levels=None, init_zoom_levels=None):
    process_zoom_levels = _validate_zooms(process_zoom_levels)
    if init_zoom_levels is None:
        return process_zoom_levels
    else:
        init_zoom_levels = _validate_zooms(init_zoom_levels)
        if not set(init_zoom_levels).issubset(set(process_zoom_levels)):
            raise MapcheteConfigError(
                "init zooms must be a subset of process zoom")
        return init_zoom_levels

Response: Validate and return zoom levels.


Instruction:
Make a summary of the following Python 3 code
def snap_bounds(bounds=None, pyramid=None, zoom=None):
    if not isinstance(bounds, (tuple, list)):
        raise TypeError("bounds must be either a tuple or a list")
    if len(bounds) != 4:
        raise ValueError("bounds has to have exactly four values")
    if not isinstance(pyramid, BufferedTilePyramid):
        raise TypeError("pyramid has to be a BufferedTilePyramid")

    bounds = Bounds(*bounds)
    lb = pyramid.tile_from_xy(bounds.left, bounds.bottom, zoom, on_edge_use="rt").bounds
    rt = pyramid.tile_from_xy(bounds.right, bounds.top, zoom, on_edge_use="lb").bounds
    return Bounds(lb.left, lb.bottom, rt.right, rt.top)

Response: Snaps bounds to tiles boundaries of specific zoom level.


Instruction:
How would you implement a function in Python 3 that
clips bounds by clip.

Response:
def clip_bounds(bounds=None, clip=None):
    """
    Clips bounds by clip.

    Parameters
    ----------
    bounds : bounds to be clipped
    clip : clip bounds

    Returns
    -------
    Bounds(left, bottom, right, top)
    """
    bounds = Bounds(*bounds)
    clip = Bounds(*clip)
    return Bounds(
        max(bounds.left, clip.left),
        max(bounds.bottom, clip.bottom),
        min(bounds.right, clip.right),
        min(bounds.top, clip.top)
    )


Instruction:
Write a Python 3 script to
load the process pyramid of a raw mapchete configuration as dictionary.

Response:
def raw_conf_process_pyramid(raw_conf):
    """
    Loads the process pyramid of a raw configuration.

    Parameters
    ----------
    raw_conf : dict
        Raw mapchete configuration as dictionary.

    Returns
    -------
    BufferedTilePyramid
    """
    return BufferedTilePyramid(
        raw_conf["pyramid"]["grid"],
        metatiling=raw_conf["pyramid"].get("metatiling", 1),
        pixelbuffer=raw_conf["pyramid"].get("pixelbuffer", 0)
    )


Instruction:
Can you implement a function in Python 3 that
loads the process pyramid of a raw mapchete configuration.

Response:
def bounds_from_opts(
    wkt_geometry=None, point=None, bounds=None, zoom=None, raw_conf=None
):
    """
    Loads the process pyramid of a raw configuration.

    Parameters
    ----------
    raw_conf : dict
        Raw mapchete configuration as dictionary.

    Returns
    -------
    BufferedTilePyramid
    """
    if wkt_geometry:
        return wkt.loads(wkt_geometry).bounds
    elif point:
        x, y = point
        zoom_levels = get_zoom_levels(
            process_zoom_levels=raw_conf["zoom_levels"],
            init_zoom_levels=zoom
        )
        tp = raw_conf_process_pyramid(raw_conf)
        return tp.tile_from_xy(x, y, max(zoom_levels)).bounds
    else:
        return bounds


Instruction:
How would you implement a function in Python 3 that
validates the zoom levels.

Response:
def _validate_zooms(zooms):
    """
    Return a list of zoom levels.

    Following inputs are converted:
    - int --> [int]
    - dict{min, max} --> range(min, max + 1)
    - [int] --> [int]
    - [int, int] --> range(smaller int, bigger int + 1)
    """
    if isinstance(zooms, dict):
        if any([a not in zooms for a in ["min", "max"]]):
            raise MapcheteConfigError("min and max zoom required")
        zmin = _validate_zoom(zooms["min"])
        zmax = _validate_zoom(zooms["max"])
        if zmin > zmax:
            raise MapcheteConfigError(
                "max zoom must not be smaller than min zoom")
        return list(range(zmin, zmax + 1))
    elif isinstance(zooms, list):
        if len(zooms) == 1:
            return zooms
        elif len(zooms) == 2:
            zmin, zmax = sorted([_validate_zoom(z) for z in zooms])
            return list(range(zmin, zmax + 1))
        else:
            return zooms
    else:
        return [_validate_zoom(zooms)]


Instruction:
How would you explain what the following Python 3 function does
def _raw_at_zoom(config, zooms):
    params_per_zoom = {}
    for zoom in zooms:
        params = {}
        for name, element in config.items():
            if name not in _RESERVED_PARAMETERS:
                out_element = _element_at_zoom(name, element, zoom)
                if out_element is not None:
                    params[name] = out_element
        params_per_zoom[zoom] = params
    return params_per_zoom

Response: Return parameter dictionary per zoom level.


Instruction:
Create a Python 3 function to
return the element at a given zoom level.

Response:
def _element_at_zoom(name, element, zoom):
        """
        Return the element filtered by zoom level.

        - An input integer or float gets returned as is.
        - An input string is checked whether it starts with "zoom". Then, the
          provided zoom level gets parsed and compared with the actual zoom
          level. If zoom levels match, the element gets returned.
        TODOs/gotchas:
        - Elements are unordered, which can lead to unexpected results when
          defining the YAML config.
        - Provided zoom levels for one element in config file are not allowed
          to "overlap", i.e. there is not yet a decision mechanism implemented
          which handles this case.
        """
        # If element is a dictionary, analyze subitems.
        if isinstance(element, dict):
            if "format" in element:
                # we have an input or output driver here
                return element
            out_elements = {}
            for sub_name, sub_element in element.items():
                out_element = _element_at_zoom(sub_name, sub_element, zoom)
                if name == "input":
                    out_elements[sub_name] = out_element
                elif out_element is not None:
                    out_elements[sub_name] = out_element
            # If there is only one subelement, collapse unless it is
            # input. In such case, return a dictionary.
            if len(out_elements) == 1 and name != "input":
                return next(iter(out_elements.values()))
            # If subelement is empty, return None
            if len(out_elements) == 0:
                return None
            return out_elements
        # If element is a zoom level statement, filter element.
        elif isinstance(name, str):
            if name.startswith("zoom"):
                return _filter_by_zoom(
                    conf_string=name.strip("zoom").strip(), zoom=zoom,
                    element=element)
            # If element is a string but not a zoom level statement, return
            # element.
            else:
                return element
        # Return all other types as they are.
        else:
            return element


Instruction:
Here you have a function in Python 3, explain what it does
def _filter_by_zoom(element=None, conf_string=None, zoom=None):
    for op_str, op_func in [
        # order of operators is important:
        # prematurely return in cases of "<=" or ">=", otherwise
        # _strip_zoom() cannot parse config strings starting with "<"
        # or ">"
        ("=", operator.eq),
        ("<=", operator.le),
        (">=", operator.ge),
        ("<", operator.lt),
        (">", operator.gt),
    ]:
        if conf_string.startswith(op_str):
            return element if op_func(zoom, _strip_zoom(conf_string, op_str)) else None

Response: Return element only if zoom condition matches with config string.


Instruction:
Write a Python 3 function for
returning zoom level as integer or throw error.

Response:
def _strip_zoom(input_string, strip_string):
    """Return zoom level as integer or throw error."""
    try:
        return int(input_string.strip(strip_string))
    except Exception as e:
        raise MapcheteConfigError("zoom level could not be determined: %s" % e)


Instruction:
Can you generate the documentation for the following Python 3 function
def _flatten_tree(tree, old_path=None):
    flat_tree = []
    for key, value in tree.items():
        new_path = "/".join([old_path, key]) if old_path else key
        if isinstance(value, dict) and "format" not in value:
            flat_tree.extend(_flatten_tree(value, old_path=new_path))
        else:
            flat_tree.append((new_path, value))
    return flat_tree

Response: Flatten dict tree into dictionary where keys are paths of old dict.


Instruction:
Can you tell what is the following Python 3 function doing
def bounds(self):
        if self._raw["bounds"] is None:
            return self.process_pyramid.bounds
        else:
            return Bounds(*_validate_bounds(self._raw["bounds"]))

Response: Process bounds as defined in the configuration.


Instruction:
Write a Python 3 function for
processing bounds this process is currently initialized with. This gets triggered by using the ``init_bounds`` kwarg. If not set, it will be equal to self.bounds.

Response:
def init_bounds(self):
        """
        Process bounds this process is currently initialized with.

        This gets triggered by using the ``init_bounds`` kwarg. If not set, it will
        be equal to self.bounds.
        """
        if self._raw["init_bounds"] is None:
            return self.bounds
        else:
            return Bounds(*_validate_bounds(self._raw["init_bounds"]))


Instruction:
Here you have a function in Python 3, explain what it does
def effective_bounds(self):
        return snap_bounds(
            bounds=clip_bounds(bounds=self.init_bounds, clip=self.process_pyramid.bounds),
            pyramid=self.process_pyramid,
            zoom=min(
                self.baselevels["zooms"]
            ) if self.baselevels else min(
                self.init_zoom_levels
            )
        )

Response: Return effective process bounds for process.


Instruction:
Create a Python 3 function to
return object of driver.

Response:
def output(self):
        """Output object of driver."""
        output_params = dict(
            self._raw["output"],
            grid=self.output_pyramid.grid,
            pixelbuffer=self.output_pyramid.pixelbuffer,
            metatiling=self.output_pyramid.metatiling
        )
        if "path" in output_params:
            output_params.update(
                path=absolute_path(path=output_params["path"], base_dir=self.config_dir)
            )

        if "format" not in output_params:
            raise MapcheteConfigError("output format not specified")

        if output_params["format"] not in available_output_formats():
            raise MapcheteConfigError(
                "format %s not available in %s" % (
                    output_params["format"], str(available_output_formats())
                )
            )
        writer = load_output_writer(output_params)
        try:
            writer.is_valid_with_config(output_params)
        except Exception as e:
            logger.exception(e)
            raise MapcheteConfigError(
                "driver %s not compatible with configuration: %s" % (
                    writer.METADATA["driver_name"], e
                )
            )
        return writer


Instruction:
Given the following Python 3 function, write the documentation
def input(self):
        # the delimiters are used by some input drivers
        delimiters = dict(
            zoom=self.init_zoom_levels,
            bounds=self.init_bounds,
            process_bounds=self.bounds,
            effective_bounds=self.effective_bounds
        )

        # get input items only of initialized zoom levels
        raw_inputs = {
            # convert input definition to hash
            get_hash(v): v
            for zoom in self.init_zoom_levels
            if "input" in self._params_at_zoom[zoom]
            # to preserve file groups, "flatten" the input tree and use
            # the tree paths as keys
            for key, v in _flatten_tree(self._params_at_zoom[zoom]["input"])
            if v is not None
        }

        initalized_inputs = {}
        for k, v in raw_inputs.items():

            # for files and tile directories
            if isinstance(v, str):
                logger.debug("load input reader for simple input %s",  v)
                try:
                    reader = load_input_reader(
                        dict(
                            path=absolute_path(path=v, base_dir=self.config_dir),
                            pyramid=self.process_pyramid,
                            pixelbuffer=self.process_pyramid.pixelbuffer,
                            delimiters=delimiters
                        ),
                        readonly=self.mode == "readonly")
                except Exception as e:
                    logger.exception(e)
                    raise MapcheteDriverError("error when loading input %s: %s" % (v, e))
                logger.debug("input reader for simple input %s is %s", v, reader)

            # for abstract inputs
            elif isinstance(v, dict):
                logger.debug("load input reader for abstract input %s", v)
                try:
                    reader = load_input_reader(
                        dict(
                            abstract=deepcopy(v),
                            pyramid=self.process_pyramid,
                            pixelbuffer=self.process_pyramid.pixelbuffer,
                            delimiters=delimiters,
                            conf_dir=self.config_dir
                        ),
                        readonly=self.mode == "readonly")
                except Exception as e:
                    logger.exception(e)
                    raise MapcheteDriverError("error when loading input %s: %s" % (v, e))
                logger.debug("input reader for abstract input %s is %s", v, reader)
            else:
                raise MapcheteConfigError("invalid input type %s", type(v))
            # trigger bbox creation
            reader.bbox(out_crs=self.process_pyramid.crs)
            initalized_inputs[k] = reader

        return initalized_inputs

Response: Load all input items from the input tree and store them in a dictionary.


Instruction:
Can you write a function in Python 3 where it
returns a dictionary of baselevels configuration parameters.

Response:
def baselevels(self):
        """
        Optional baselevels configuration.

        baselevels:
            min: <zoom>
            max: <zoom>
            lower: <resampling method>
            higher: <resampling method>
        """
        if "baselevels" not in self._raw:
            return {}
        baselevels = self._raw["baselevels"]
        minmax = {k: v for k, v in baselevels.items() if k in ["min", "max"]}

        if not minmax:
            raise MapcheteConfigError("no min and max values given for baselevels")
        for v in minmax.values():
            if not isinstance(v, int) or v < 0:
                raise MapcheteConfigError(
                    "invalid baselevel zoom parameter given: %s" % minmax.values()
                )

        zooms = list(range(
            minmax.get("min", min(self.zoom_levels)),
            minmax.get("max", max(self.zoom_levels)) + 1)
        )

        if not set(self.zoom_levels).difference(set(zooms)):
            raise MapcheteConfigError("baselevels zooms fully cover process zooms")

        return dict(
            zooms=zooms,
            lower=baselevels.get("lower", "nearest"),
            higher=baselevels.get("higher", "nearest"),
            tile_pyramid=BufferedTilePyramid(
                self.output_pyramid.grid,
                pixelbuffer=self.output_pyramid.pixelbuffer,
                metatiling=self.process_pyramid.metatiling
            )
        )


Instruction:
Implement a Python 3 function for
returning configuration parameters snapshot for zoom level dependent process configuration.

Response:
def params_at_zoom(self, zoom):
        """
        Return configuration parameters snapshot for zoom as dictionary.

        Parameters
        ----------
        zoom : int
            zoom level

        Returns
        -------
        configuration snapshot : dictionary
        zoom level dependent process configuration
        """
        if zoom not in self.init_zoom_levels:
            raise ValueError(
                "zoom level not available with current configuration")
        out = dict(self._params_at_zoom[zoom], input={}, output=self.output)
        if "input" in self._params_at_zoom[zoom]:
            flat_inputs = {}
            for k, v in _flatten_tree(self._params_at_zoom[zoom]["input"]):
                if v is None:
                    flat_inputs[k] = None
                else:
                    flat_inputs[k] = self.input[get_hash(v)]
            out["input"] = _unflatten_tree(flat_inputs)
        else:
            out["input"] = {}
        return out


Instruction:
Write a Python 3 script to
return the area of the process at a given zoom level.

Response:
def area_at_zoom(self, zoom=None):
        """
        Return process bounding box for zoom level.

        Parameters
        ----------
        zoom : int or None
            if None, the union of all zoom level areas is returned

        Returns
        -------
        process area : shapely geometry
        """
        if zoom is None:
            if not self._cache_full_process_area:
                logger.debug("calculate process area ...")
                self._cache_full_process_area = cascaded_union([
                    self._area_at_zoom(z) for z in self.init_zoom_levels]
                ).buffer(0)
            return self._cache_full_process_area
        else:
            if zoom not in self.init_zoom_levels:
                raise ValueError(
                    "zoom level not available with current configuration")
            return self._area_at_zoom(zoom)


Instruction:
Can you generate the documentation for the following Python 3 function
def bounds_at_zoom(self, zoom=None):
        return () if self.area_at_zoom(zoom).is_empty else Bounds(
            *self.area_at_zoom(zoom).bounds)

Response: Return process bounds at zoom level.


Instruction:
Explain what the following Python 3 code does
def process_file(self):
        warnings.warn(DeprecationWarning("'self.process_file' is deprecated"))
        return os.path.join(self._raw["config_dir"], self._raw["process"])

Response: Return the path to the process file.


Instruction:
Implement a function in Python 3 to
generate index files for given zoom level.

Response:
def zoom_index_gen(
    mp=None,
    out_dir=None,
    zoom=None,
    geojson=False,
    gpkg=False,
    shapefile=False,
    txt=False,
    vrt=False,
    fieldname="location",
    basepath=None,
    for_gdal=True,
    threading=False,
):
    """
    Generate indexes for given zoom level.

    Parameters
    ----------
    mp : Mapchete object
        process output to be indexed
    out_dir : path
        optionally override process output directory
    zoom : int
        zoom level to be processed
    geojson : bool
        generate GeoJSON index (default: False)
    gpkg : bool
        generate GeoPackage index (default: False)
    shapefile : bool
        generate Shapefile index (default: False)
    txt : bool
        generate tile path list textfile (default: False)
    vrt : bool
        GDAL-style VRT file (default: False)
    fieldname : str
        field name which contains paths of tiles (default: "location")
    basepath : str
        if set, use custom base path instead of output path
    for_gdal : bool
        use GDAL compatible remote paths, i.e. add "/vsicurl/" before path
        (default: True)
    """
    for zoom in get_zoom_levels(process_zoom_levels=zoom):
        with ExitStack() as es:
            # get index writers for all enabled formats
            index_writers = []
            if geojson:
                index_writers.append(
                    es.enter_context(
                        VectorFileWriter(
                            driver="GeoJSON",
                            out_path=_index_file_path(out_dir, zoom, "geojson"),
                            crs=mp.config.output_pyramid.crs,
                            fieldname=fieldname
                        )
                    )
                )
            if gpkg:
                index_writers.append(
                    es.enter_context(
                        VectorFileWriter(
                            driver="GPKG",
                            out_path=_index_file_path(out_dir, zoom, "gpkg"),
                            crs=mp.config.output_pyramid.crs,
                            fieldname=fieldname
                        )
                    )
                )
            if shapefile:
                index_writers.append(
                    es.enter_context(
                        VectorFileWriter(
                            driver="ESRI Shapefile",
                            out_path=_index_file_path(out_dir, zoom, "shp"),
                            crs=mp.config.output_pyramid.crs,
                            fieldname=fieldname
                        )
                    )
                )
            if txt:
                index_writers.append(
                    es.enter_context(
                        TextFileWriter(out_path=_index_file_path(out_dir, zoom, "txt"))
                    )
                )
            if vrt:
                index_writers.append(
                    es.enter_context(
                        VRTFileWriter(
                            out_path=_index_file_path(out_dir, zoom, "vrt"),
                            output=mp.config.output,
                            out_pyramid=mp.config.output_pyramid
                        )
                    )
                )

            logger.debug("use the following index writers: %s", index_writers)

            def _worker(tile):
                # if there are indexes to write to, check if output exists
                tile_path = _tile_path(
                    orig_path=mp.config.output.get_path(tile),
                    basepath=basepath,
                    for_gdal=for_gdal
                )
                indexes = [
                    i for i in index_writers
                    if not i.entry_exists(tile=tile, path=tile_path)
                ]
                if indexes:
                    output_exists = mp.config.output.tiles_exist(output_tile=tile)
                else:
                    output_exists = None
                return tile, tile_path, indexes, output_exists

            with concurrent.futures.ThreadPoolExecutor() as executor:
                for task in concurrent.futures.as_completed(
                    (
                        executor.submit(_worker, i)
                        for i in mp.config.output_pyramid.tiles_from_geom(
                            mp.config.area_at_zoom(zoom), zoom
                        )
                    )
                ):
                    tile, tile_path, indexes, output_exists = task.result()
                    # only write entries if there are indexes to write to and output
                    # exists
                    if indexes and output_exists:
                        logger.debug("%s exists", tile_path)
                        logger.debug("write to %s indexes" % len(indexes))
                        for index in indexes:
                            index.write(tile, tile_path)
                    # yield tile for progress information
                    yield tile


Instruction:
Make a summary of the following Python 3 code
def get_segmentize_value(input_file=None, tile_pyramid=None):
    warnings.warn(DeprecationWarning("get_segmentize_value() has moved to mapchete.io"))
    return io.get_segmentize_value(input_file, tile_pyramid)

Response: Returns the recommended segmentation value in input file units.


Instruction:
Write a Python 3 function for
returning the bounding box of the data in the specified CRS.

Response:
def bbox(self, out_crs=None):
        """
        Return data bounding box.

        Parameters
        ----------
        out_crs : ``rasterio.crs.CRS``
            rasterio CRS object (default: CRS of process pyramid)

        Returns
        -------
        bounding box : geometry
            Shapely geometry object
        """
        out_crs = self.pyramid.crs if out_crs is None else out_crs
        with rasterio.open(self.path) as inp:
            inp_crs = inp.crs
            out_bbox = bbox = box(*inp.bounds)
        # If soucre and target CRSes differ, segmentize and reproject
        if inp_crs != out_crs:
            # estimate segmentize value (raster pixel size * tile size)
            # and get reprojected bounding box
            return reproject_geometry(
                segmentize_geometry(
                    bbox, inp.transform[0] * self.pyramid.tile_size
                ),
                src_crs=inp_crs, dst_crs=out_crs
            )
        else:
            return out_bbox


Instruction:
Given the following Python 3 function, write the documentation
def read(self, indexes=None, **kwargs):
        return read_raster_window(
            self.raster_file.path,
            self.tile,
            indexes=self._get_band_indexes(indexes),
            resampling=self.resampling,
            gdal_opts=self.gdal_opts
        )

Response: Read reprojected & resampled input data.


Instruction:
Create a Python 3 function to
check if the data within this tile is empty.

Response:
def is_empty(self, indexes=None):
        """
        Check if there is data within this tile.

        Returns
        -------
        is empty : bool
        """
        # empty if tile does not intersect with file bounding box
        return not self.tile.bbox.intersects(
            self.raster_file.bbox(out_crs=self.tile.crs)
        )


Instruction:
Can you generate the documentation for the following Python 3 function
def _get_band_indexes(self, indexes=None):
        if indexes:
            if isinstance(indexes, list):
                return indexes
            else:
                return [indexes]
        else:
            return range(1, self.raster_file.profile["count"] + 1)

Response: Return valid band indexes.


Instruction:
How would you explain what the following Python 3 function does
def read(self, output_tile, **kwargs):
        path = self.get_path(output_tile)
        try:
            with fiona.open(path, "r") as src:
                return list(src)
        except DriverError as e:
            for i in ("does not exist in the file system", "No such file or directory"):
                if i in str(e):
                    return self.empty(output_tile)
            else:
                raise

Response: Read existing process output.


Instruction:
Can you write a function in Python 3 where it
writes data from process tiles into GeoJSON file.

Response:
def write(self, process_tile, data):
        """
        Write data from process tiles into GeoJSON file(s).

        Parameters
        ----------
        process_tile : ``BufferedTile``
            must be member of process ``TilePyramid``
        """
        if data is None or len(data) == 0:
            return
        if not isinstance(data, (list, types.GeneratorType)):
            raise TypeError(
                "GeoJSON driver data has to be a list or generator of GeoJSON objects"
            )

        data = list(data)

        if not len(data):
            logger.debug("no features to write")
        else:
            # in case of S3 output, create an boto3 resource
            bucket_resource = get_boto3_bucket(self._bucket) if self._bucket else None

            # Convert from process_tile to output_tiles
            for tile in self.pyramid.intersecting(process_tile):
                out_path = self.get_path(tile)
                self.prepare_path(tile)
                out_tile = BufferedTile(tile, self.pixelbuffer)
                write_vector_window(
                    in_data=data,
                    out_schema=self.output_params["schema"],
                    out_tile=out_tile,
                    out_path=out_path,
                    bucket_resource=bucket_resource
                )


Instruction:
Write a Python 3 function that can
check if output format is valid with other process parameters.

Response:
def is_valid_with_config(self, config):
        """
        Check if output format is valid with other process parameters.

        Parameters
        ----------
        config : dictionary
            output configuration parameters

        Returns
        -------
        is_valid : bool
        """
        validate_values(config, [("schema", dict), ("path", str)])
        validate_values(config["schema"], [("properties", dict), ("geometry", str)])
        if config["schema"]["geometry"] not in [
            "Geometry", "Point", "MultiPoint", "Line", "MultiLine",
            "Polygon", "MultiPolygon"
        ]:
            raise TypeError("invalid geometry type")
        return True


Instruction:
Given the following Python 3 function, write the documentation
def read(self, validity_check=True, no_neighbors=False, **kwargs):
        if no_neighbors:
            raise NotImplementedError()
        return self._from_cache(validity_check=validity_check)

Response: Read data from process output.


Instruction:
Implement a Python 3 function for
executing a Mapchete process.

Response:
def execute(
    mapchete_files,
    zoom=None,
    bounds=None,
    point=None,
    wkt_geometry=None,
    tile=None,
    overwrite=False,
    multi=None,
    input_file=None,
    logfile=None,
    verbose=False,
    no_pbar=False,
    debug=False,
    max_chunksize=None,
    vrt=False,
    idx_out_dir=None
):
    """Execute a Mapchete process."""
    multi = multi if multi else cpu_count()
    mode = "overwrite" if overwrite else "continue"
    # send verbose messages to /dev/null if not activated
    if debug or not verbose:
        verbose_dst = open(os.devnull, 'w')
    else:
        verbose_dst = sys.stdout

    for mapchete_file in mapchete_files:

        tqdm.tqdm.write("preparing to process %s" % mapchete_file, file=verbose_dst)

        with click_spinner.spinner(disable=debug) as spinner:

            # process single tile
            if tile:
                tile = raw_conf_process_pyramid(raw_conf(mapchete_file)).tile(*tile)

                with mapchete.open(
                    mapchete_file,
                    mode=mode,
                    bounds=tile.bounds,
                    zoom=tile.zoom,
                    single_input_file=input_file
                ) as mp:
                    spinner.stop()
                    tqdm.tqdm.write("processing 1 tile", file=verbose_dst)

                    # run process on tile
                    for result in mp.batch_processor(tile=tile):
                        utils.write_verbose_msg(result, dst=verbose_dst)
                    tqdm.tqdm.write(
                        "processing %s finished" % mapchete_file, file=verbose_dst
                    )

                    # write VRT index
                    if vrt:
                        tqdm.tqdm.write("creating VRT", file=verbose_dst)
                        for tile in tqdm.tqdm(
                            zoom_index_gen(
                                mp=mp,
                                zoom=tile.zoom,
                                out_dir=(
                                    idx_out_dir if idx_out_dir else mp.config.output.path
                                ),
                                vrt=vrt,
                            ),
                            total=mp.count_tiles(tile.zoom, tile.zoom),
                            unit="tile",
                            disable=debug or no_pbar
                        ):
                            logger.debug("%s indexed", tile)
                        tqdm.tqdm.write(
                            "VRT(s) creation for %s finished" % mapchete_file,
                            file=verbose_dst
                        )

            # process area
            else:
                with mapchete.open(
                    mapchete_file,
                    mode=mode,
                    zoom=zoom,
                    bounds=bounds_from_opts(
                        wkt_geometry=wkt_geometry,
                        point=point,
                        bounds=bounds,
                        raw_conf=raw_conf(mapchete_file)
                    ),
                    single_input_file=input_file
                ) as mp:
                    spinner.stop()
                    tiles_count = mp.count_tiles(
                        min(mp.config.init_zoom_levels),
                        max(mp.config.init_zoom_levels)
                    )
                    tqdm.tqdm.write(
                        "processing %s tile(s) on %s worker(s)" % (tiles_count, multi),
                        file=verbose_dst
                    )

                    # run process on tiles
                    for process_info in tqdm.tqdm(
                        mp.batch_processor(
                            multi=multi, zoom=zoom, max_chunksize=max_chunksize
                        ),
                        total=tiles_count,
                        unit="tile",
                        disable=debug or no_pbar
                    ):
                        utils.write_verbose_msg(process_info, dst=verbose_dst)
                    tqdm.tqdm.write(
                        "processing %s finished" % mapchete_file, file=verbose_dst
                    )

                    # write VRT index
                    if vrt:
                        tqdm.tqdm.write("creating VRT(s)", file=verbose_dst)
                        for tile in tqdm.tqdm(
                            zoom_index_gen(
                                mp=mp,
                                zoom=mp.config.init_zoom_levels,
                                out_dir=(
                                    idx_out_dir if idx_out_dir
                                    else mp.config.output.path
                                ),
                                vrt=vrt
                            ),
                            total=mp.count_tiles(
                                min(mp.config.init_zoom_levels),
                                max(mp.config.init_zoom_levels)
                            ),
                            unit="tile",
                            disable=debug or no_pbar
                        ):
                            logger.debug("%s indexed", tile)
                        tqdm.tqdm.write(
                            "VRT(s) creation for %s finished" % mapchete_file,
                            file=verbose_dst
                        )


Instruction:
Make a summary of the following Python 3 code
def available_output_formats():
    output_formats = []
    for v in pkg_resources.iter_entry_points(DRIVERS_ENTRY_POINT):
        driver_ = v.load()
        if hasattr(driver_, "METADATA") and (
            driver_.METADATA["mode"] in ["w", "rw"]
        ):
            output_formats.append(driver_.METADATA["driver_name"])
    return output_formats

Response: Return all available output formats.


Instruction:
How would you implement a function in Python 3 that
returns all available input formats.

Response:
def available_input_formats():
    """
    Return all available input formats.

    Returns
    -------
    formats : list
        all available input formats
    """
    input_formats = []
    for v in pkg_resources.iter_entry_points(DRIVERS_ENTRY_POINT):
        logger.debug("driver found: %s", v)
        driver_ = v.load()
        if hasattr(driver_, "METADATA") and (driver_.METADATA["mode"] in ["r", "rw"]):
            input_formats.append(driver_.METADATA["driver_name"])
    return input_formats


Instruction:
Can you tell what is the following Python 3 function doing
def load_output_writer(output_params, readonly=False):
    if not isinstance(output_params, dict):
        raise TypeError("output_params must be a dictionary")
    driver_name = output_params["format"]
    for v in pkg_resources.iter_entry_points(DRIVERS_ENTRY_POINT):
        _driver = v.load()
        if all(
            [hasattr(_driver, attr) for attr in ["OutputData", "METADATA"]]
            ) and (
            _driver.METADATA["driver_name"] == driver_name
        ):
            return _driver.OutputData(output_params, readonly=readonly)
    raise MapcheteDriverError("no loader for driver '%s' could be found." % driver_name)

Response: Load the output class of driver.


Instruction:
Implement a function in Python 3 to
load input class of driver.

Response:
def load_input_reader(input_params, readonly=False):
    """
    Return input class of driver.

    Returns
    -------
    input_params : ``InputData``
        input parameters
    """
    logger.debug("find input reader with params %s", input_params)
    if not isinstance(input_params, dict):
        raise TypeError("input_params must be a dictionary")
    if "abstract" in input_params:
        driver_name = input_params["abstract"]["format"]
    elif "path" in input_params:
        if os.path.splitext(input_params["path"])[1]:
            input_file = input_params["path"]
            driver_name = driver_from_file(input_file)
        else:
            logger.debug("%s is a directory", input_params["path"])
            driver_name = "TileDirectory"
    else:
        raise MapcheteDriverError("invalid input parameters %s" % input_params)
    for v in pkg_resources.iter_entry_points(DRIVERS_ENTRY_POINT):
        driver_ = v.load()
        if hasattr(driver_, "METADATA") and (
            driver_.METADATA["driver_name"] == driver_name
        ):
            return v.load().InputData(input_params, readonly=readonly)
    raise MapcheteDriverError("no loader for driver '%s' could be found." % driver_name)


Instruction:
Here you have a function in Python 3, explain what it does
def driver_from_file(input_file):
    file_ext = os.path.splitext(input_file)[1].split(".")[1]
    if file_ext not in _file_ext_to_driver():
        raise MapcheteDriverError(
            "no driver could be found for file extension %s" % file_ext
        )
    driver = _file_ext_to_driver()[file_ext]
    if len(driver) > 1:
        warnings.warn(
            DeprecationWarning(
                "more than one driver for file found, taking %s" % driver[0]
            )
        )
    return driver[0]

Response: Guess driver from file extension.


Instruction:
Write a Python 3 script to
dump output JSON and verify parameters if output metadata exist.

Response:
def write_output_metadata(output_params):
    """Dump output JSON and verify parameters if output metadata exist."""
    if "path" in output_params:
        metadata_path = os.path.join(output_params["path"], "metadata.json")
        logger.debug("check for output %s", metadata_path)
        try:
            existing_params = read_output_metadata(metadata_path)
            logger.debug("%s exists", metadata_path)
            logger.debug("existing output parameters: %s", pformat(existing_params))
            existing_tp = existing_params["pyramid"]
            current_params = params_to_dump(output_params)
            logger.debug("current output parameters: %s", pformat(current_params))
            current_tp = BufferedTilePyramid(**current_params["pyramid"])
            if existing_tp != current_tp:
                raise MapcheteConfigError(
                    "pyramid definitions between existing and new output do not match: "
                    "%s != %s" % (existing_tp, current_tp)
                )
            existing_format = existing_params["driver"]["format"]
            current_format = current_params["driver"]["format"]
            if existing_format != current_format:
                raise MapcheteConfigError(
                    "existing output format does not match new output format: "
                    "%s != %s" % (
                        (existing_format, current_format)
                    )
                )
        except FileNotFoundError:
            logger.debug("%s does not exist", metadata_path)
            dump_params = params_to_dump(output_params)
            # dump output metadata
            write_json(metadata_path, dump_params)
    else:
        logger.debug("no path parameter found")


Instruction:
Implement a Python 3 function for
listing input and output formats.

Response:
def formats(input_formats, output_formats, debug=False):
    """List input and/or output formats."""
    if input_formats == output_formats:
        show_inputs, show_outputs = True, True
    else:
        show_inputs, show_outputs = input_formats, output_formats

    if show_inputs:
        click.echo("input formats:")
        for driver in available_input_formats():
            click.echo("- %s" % driver)
    if show_outputs:
        click.echo("output formats:")
        for driver in available_output_formats():
            click.echo("- %s" % driver)


Instruction:
How would you code a function in Python 3 to
open a new input tile and return a new InputTile object.

Response:
def open(
        self,
        tile,
        tile_directory_zoom=None,
        matching_method="gdal",
        matching_max_zoom=None,
        matching_precision=8,
        fallback_to_higher_zoom=False,
        resampling="nearest",
        **kwargs
    ):
        """
        Return InputTile object.

        Parameters
        ----------
        tile : ``Tile``
        tile_directory_zoom : None
            If set, data will be read from exactly this zoom level
        matching_method : str ('gdal' or 'min') (default: 'gdal')
            gdal: Uses GDAL's standard method. Here, the target resolution is calculated
                by averaging the extent's pixel sizes over both x and y axes. This
                approach returns a zoom level which may not have the best quality but will
                speed up reading significantly.
            min: Returns the zoom level which matches the minimum resolution of the
                extents four corner pixels. This approach returns the zoom level with the
                best possible quality but with low performance. If the tile extent is
                outside of the destination pyramid, a TopologicalError will be raised.
        matching_max_zoom : int (default: None)
            If set, it will prevent reading from zoom levels above the maximum.
        matching_precision : int
            Round resolutions to n digits before comparing.
        fallback_to_higher_zoom : bool (default: False)
            In case no data is found at zoom level, try to read data from higher zoom
            levels. Enabling this setting can lead to many IO requests in areas with no
            data.
        resampling : string
            raster file: one of "nearest", "average", "bilinear" or "lanczos"

        Returns
        -------
        input tile : ``InputTile``
            tile view of input data
        """
        # determine tile bounds in TileDirectory CRS
        td_bounds = reproject_geometry(
            tile.bbox,
            src_crs=tile.tp.crs,
            dst_crs=self.td_pyramid.crs
        ).bounds

        # find target zoom level
        if tile_directory_zoom is not None:
            zoom = tile_directory_zoom
        else:
            zoom = tile_to_zoom_level(
                tile, dst_pyramid=self.td_pyramid, matching_method=matching_method,
                precision=matching_precision
            )
            if matching_max_zoom is not None:
                zoom = min([zoom, matching_max_zoom])

        if fallback_to_higher_zoom:
            tiles_paths = []
            # check if tiles exist otherwise try higher zoom level
            while len(tiles_paths) == 0 and zoom >= 0:
                tiles_paths = _get_tiles_paths(
                    basepath=self.path,
                    ext=self._ext,
                    pyramid=self.td_pyramid,
                    bounds=td_bounds,
                    zoom=zoom
                )
                logger.debug("%s existing tiles found at zoom %s", len(tiles_paths), zoom)
                zoom -= 1
        else:
            tiles_paths = _get_tiles_paths(
                basepath=self.path,
                ext=self._ext,
                pyramid=self.td_pyramid,
                bounds=td_bounds,
                zoom=zoom
            )
            logger.debug("%s existing tiles found at zoom %s", len(tiles_paths), zoom)
        return InputTile(
            tile,
            tiles_paths=tiles_paths,
            file_type=self._file_type,
            profile=self._profile,
            td_crs=self.td_pyramid.crs,
            resampling=resampling,
            read_as_tiledir_func=self._read_as_tiledir_func,
            **kwargs
        )


Instruction:
Make a summary of the following Python 3 code
def bbox(self, out_crs=None):
        return reproject_geometry(
            box(*self._bounds),
            src_crs=self.td_pyramid.crs,
            dst_crs=self.pyramid.crs if out_crs is None else out_crs
        )

Response: Return data bounding box.


Instruction:
Create a Python 3 function to
read the data from the target dataset into a list of tuples.

Response:
def read(
        self,
        validity_check=False,
        indexes=None,
        resampling=None,
        dst_nodata=None,
        gdal_opts=None,
        **kwargs
    ):
        """
        Read reprojected & resampled input data.

        Parameters
        ----------
        validity_check : bool
            vector file: also run checks if reprojected geometry is valid,
            otherwise throw RuntimeError (default: True)

        indexes : list or int
            raster file: a list of band numbers; None will read all.
        dst_nodata : int or float, optional
            raster file: if not set, the nodata value from the source dataset
            will be used
        gdal_opts : dict
            raster file: GDAL options passed on to rasterio.Env()

        Returns
        -------
        data : list for vector files or numpy array for raster files
        """
        return self._read_as_tiledir(
            data_type=self._file_type,
            out_tile=self.tile,
            td_crs=self._td_crs,
            tiles_paths=self._tiles_paths,
            profile=self._profile,
            validity_check=validity_check,
            indexes=indexes,
            resampling=resampling if resampling else self._resampling,
            dst_nodata=dst_nodata,
            gdal_opts=gdal_opts,
            **{k: v for k, v in kwargs.items() if k != "data_type"}
        )


Instruction:
Create a Python 3 function to
extract contour lines from an array.

Response:
def extract_contours(array, tile, interval=100, field='elev', base=0):
    """
    Extract contour lines from an array.

    Parameters
    ----------
    array : array
        input elevation data
    tile : Tile
        tile covering the array
    interval : integer
        elevation value interval when drawing contour lines
    field : string
        output field name containing elevation value
    base : integer
        elevation base value the intervals are computed from

    Returns
    -------
    contours : iterable
        contours as GeoJSON-like pairs of properties and geometry
    """
    import matplotlib.pyplot as plt
    levels = _get_contour_values(
        array.min(), array.max(), interval=interval, base=base)
    if not levels:
        return []
    contours = plt.contour(array, levels)
    index = 0
    out_contours = []
    for level in range(len(contours.collections)):
        elevation = levels[index]
        index += 1
        paths = contours.collections[level].get_paths()
        for path in paths:
            out_coords = [
                (
                    tile.left + (y * tile.pixel_x_size),
                    tile.top - (x * tile.pixel_y_size),
                )
                for x, y in zip(path.vertices[:, 1], path.vertices[:, 0])
            ]
            if len(out_coords) >= 2:
                out_contours.append(
                    dict(
                        properties={field: elevation},
                        geometry=mapping(LineString(out_coords))
                    )
                )
    return out_contours


Instruction:
Can you implement a function in Python 3 that
returns a list of values between min and max within an interval.

Response:
def _get_contour_values(min_val, max_val, base=0, interval=100):
    """Return a list of values between min and max within an interval."""
    i = base
    out = []
    if min_val < base:
        while i >= min_val:
            i -= interval
    while i <= max_val:
        if i >= min_val:
            out.append(i)
        i += interval
    return out


Instruction:
Can you implement a function in Python 3 that
creates an empty Mapchete and process file in a given directory.

Response:
def create(
    mapchete_file,
    process_file,
    out_format,
    out_path=None,
    pyramid_type=None,
    force=False
):
    """Create an empty Mapchete and process file in a given directory."""
    if os.path.isfile(process_file) or os.path.isfile(mapchete_file):
        if not force:
            raise IOError("file(s) already exists")

    out_path = out_path if out_path else os.path.join(os.getcwd(), "output")

    # copy file template to target directory
    process_template = pkg_resources.resource_filename(
        "mapchete.static", "process_template.py"
    )
    process_file = os.path.join(os.getcwd(), process_file)
    copyfile(process_template, process_file)

    # modify and copy mapchete file template to target directory
    mapchete_template = pkg_resources.resource_filename(
        "mapchete.static", "mapchete_template.mapchete"
    )

    output_options = dict(
        format=out_format, path=out_path, **FORMAT_MANDATORY[out_format]
    )

    pyramid_options = {'grid': pyramid_type}

    substitute_elements = {
        'process_file': process_file,
        'output': dump({'output': output_options}, default_flow_style=False),
        'pyramid': dump({'pyramid': pyramid_options}, default_flow_style=False)
    }
    with open(mapchete_template, 'r') as config_template:
        config = Template(config_template.read())
        customized_config = config.substitute(substitute_elements)
    with open(mapchete_file, 'w') as target_config:
        target_config.write(customized_config)


Instruction:
Can you implement a function in Python 3 that
checks whether output tiles of a tile exist.

Response:
def tiles_exist(self, process_tile=None, output_tile=None):
        """
        Check whether output tiles of a tile (either process or output) exists.

        Parameters
        ----------
        process_tile : ``BufferedTile``
            must be member of process ``TilePyramid``
        output_tile : ``BufferedTile``
            must be member of output ``TilePyramid``

        Returns
        -------
        exists : bool
        """
        if process_tile and output_tile:
            raise ValueError("just one of 'process_tile' and 'output_tile' allowed")
        if process_tile:
            return any(
                path_exists(self.get_path(tile))
                for tile in self.pyramid.intersecting(process_tile)
            )
        if output_tile:
            return path_exists(self.get_path(output_tile))


Instruction:
Make a summary of the following Python 3 code
def get_path(self, tile):
        return os.path.join(*[
            self.path,
            str(tile.zoom),
            str(tile.row),
            str(tile.col) + self.file_extension
        ])

Response: Determine target file path.


Instruction:
How would you explain what the following Python 3 function does
def prepare_path(self, tile):
        makedirs(os.path.dirname(self.get_path(tile)))

Response: Create directory and subdirectory if necessary.


Instruction:
Make a summary of the following Python 3 code
def output_is_valid(self, process_data):
        if self.METADATA["data_type"] == "raster":
            return (
                is_numpy_or_masked_array(process_data) or
                is_numpy_or_masked_array_with_tags(process_data)
            )
        elif self.METADATA["data_type"] == "vector":
            return is_feature_list(process_data)

Response: Check whether process output is allowed with output driver.


Instruction:
How would you code a function in Python 3 to
return verified and cleaned output. Parameters ---------- process_data : raw process output Returns ------- NumPy array or list of features.

Response:
def output_cleaned(self, process_data):
        """
        Return verified and cleaned output.

        Parameters
        ----------
        process_data : raw process output

        Returns
        -------
        NumPy array or list of features.
        """
        if self.METADATA["data_type"] == "raster":
            if is_numpy_or_masked_array(process_data):
                return process_data
            elif is_numpy_or_masked_array_with_tags(process_data):
                data, tags = process_data
                return self.output_cleaned(data), tags
        elif self.METADATA["data_type"] == "vector":
            return list(process_data)


Instruction:
Explain what the following Python 3 code does
def extract_subset(self, input_data_tiles=None, out_tile=None):
        if self.METADATA["data_type"] == "raster":
            mosaic = create_mosaic(input_data_tiles)
            return extract_from_array(
                in_raster=prepare_array(
                    mosaic.data,
                    nodata=self.nodata,
                    dtype=self.output_params["dtype"]
                ),
                in_affine=mosaic.affine,
                out_tile=out_tile
            )
        elif self.METADATA["data_type"] == "vector":
            return [
                feature for feature in list(
                    chain.from_iterable([features for _, features in input_data_tiles])
                )
                if shape(feature["geometry"]).intersects(out_tile.bbox)
            ]

Response: Extract subset from multiple tiles.


Instruction:
Can you generate the documentation for the following Python 3 function
def _read_as_tiledir(
        self,
        out_tile=None,
        td_crs=None,
        tiles_paths=None,
        profile=None,
        validity_check=False,
        indexes=None,
        resampling=None,
        dst_nodata=None,
        gdal_opts=None,
        **kwargs
    ):
        """
        Read reprojected & resampled input data.

        Parameters
        ----------
        validity_check : bool
            vector file: also run checks if reprojected geometry is valid,
            otherwise throw RuntimeError (default: True)

        indexes : list or int
            raster file: a list of band numbers; None will read all.
        dst_nodata : int or float, optional
            raster file: if not set, the nodata value from the source dataset
            will be used
        gdal_opts : dict
            raster file: GDAL options passed on to rasterio.Env()

        Returns
        -------
        data : list for vector files or numpy array for raster files
        """
        return _read_as_tiledir(
            data_type=self.METADATA["data_type"],
            out_tile=out_tile,
            td_crs=td_crs,
            tiles_paths=tiles_paths,
            profile=profile,
            validity_check=validity_check,
            indexes=indexes,
            resampling=resampling,
            dst_nodata=dst_nodata,
            gdal_opts=gdal_opts,
            **{k: v for k, v in kwargs.items() if k != "data_type"}
        )

Response: Read the data from the reprojected and resampled input files into a list of tile directories.


Instruction:
How would you code a function in Python 3 to
calculate the slope and aspect map of a single resource.

Response:
def calculate_slope_aspect(elevation, xres, yres, z=1.0, scale=1.0):
    """
    Calculate slope and aspect map.

    Return a pair of arrays 2 pixels smaller than the input elevation array.

    Slope is returned in radians, from 0 for sheer face to pi/2 for
    flat ground. Aspect is returned in radians, counterclockwise from -pi
    at north around to pi.

    Logic here is borrowed from hillshade.cpp:
    http://www.perrygeo.net/wordpress/?p=7

    Parameters
    ----------
    elevation : array
        input elevation data
    xres : float
        column width
    yres : float
        row  height
    z : float
        vertical exaggeration factor
    scale : float
        scale factor of pixel size units versus height units (insert 112000
        when having elevation values in meters in a geodetic projection)

    Returns
    -------
    slope shade : array
    """
    z = float(z)
    scale = float(scale)
    height, width = elevation.shape[0] - 2, elevation.shape[1] - 2
    window = [
        z * elevation[row:(row + height), col:(col + width)]
        for (row, col) in product(range(3), range(3))
    ]
    x = (
        (window[0] + window[3] + window[3] + window[6])
        - (window[2] + window[5] + window[5] + window[8])
        ) / (8.0 * xres * scale)
    y = (
        (window[6] + window[7] + window[7] + window[8])
        - (window[0] + window[1] + window[1] + window[2])
        ) / (8.0 * yres * scale)
    # in radians, from 0 to pi/2
    slope = math.pi/2 - np.arctan(np.sqrt(x*x + y*y))
    # in radians counterclockwise, from -pi at north back to pi
    aspect = np.arctan2(x, y)
    return slope, aspect


Instruction:
Write a Python 3 function that can
return the hillshaded numpy array.

Response:
def hillshade(elevation, tile, azimuth=315.0, altitude=45.0, z=1.0, scale=1.0):
    """
    Return hillshaded numpy array.

    Parameters
    ----------
    elevation : array
        input elevation data
    tile : Tile
        tile covering the array
    z : float
        vertical exaggeration factor
    scale : float
        scale factor of pixel size units versus height units (insert 112000
        when having elevation values in meters in a geodetic projection)
    """
    azimuth = float(azimuth)
    altitude = float(altitude)
    z = float(z)
    scale = float(scale)
    xres = tile.tile.pixel_x_size
    yres = -tile.tile.pixel_y_size
    slope, aspect = calculate_slope_aspect(
        elevation, xres, yres, z=z, scale=scale)
    deg2rad = math.pi / 180.0
    shaded = np.sin(altitude * deg2rad) * np.sin(slope) \
        + np.cos(altitude * deg2rad) * np.cos(slope) \
        * np.cos((azimuth - 90.0) * deg2rad - aspect)
    # shaded now has values between -1.0 and +1.0
    # stretch to 0 - 255 and invert
    shaded = (((shaded+1.0)/2)*-255.0).astype("uint8")
    # add one pixel padding using the edge values
    return ma.masked_array(
        data=np.pad(shaded, 1, mode='edge'), mask=elevation.mask
    )


Instruction:
Explain what the following Python 3 code does
def tile(self, zoom, row, col):
        tile = self.tile_pyramid.tile(zoom, row, col)
        return BufferedTile(tile, pixelbuffer=self.pixelbuffer)

Response: Return a buffered tile object of this BufferedTilePyramid.


Instruction:
Can you tell what is the following Python 3 function doing
def tiles_from_bounds(self, bounds, zoom):
        for tile in self.tiles_from_bbox(box(*bounds), zoom):
            yield self.tile(*tile.id)

Response: Yield all tiles intersecting with bounds.


Instruction:
How would you implement a function in Python 3 that
yields all metatiles intersecting with given bounding box.

Response:
def tiles_from_bbox(self, geometry, zoom):
        """
        All metatiles intersecting with given bounding box.

        Parameters
        ----------
        geometry : ``shapely.geometry``
        zoom : integer
            zoom level

        Yields
        ------
        intersecting tiles : generator
            generates ``BufferedTiles``
        """
        for tile in self.tile_pyramid.tiles_from_bbox(geometry, zoom):
            yield self.tile(*tile.id)


Instruction:
Can you generate the documentation for the following Python 3 function
def tiles_from_geom(self, geometry, zoom):
        for tile in self.tile_pyramid.tiles_from_geom(geometry, zoom):
            yield self.tile(*tile.id)

Response: Yield all tiles intersecting with input geometry.


Instruction:
Create a Python 3 function for
returning all BufferedTiles intersecting with tile.

Response:
def intersecting(self, tile):
        """
        Return all BufferedTiles intersecting with tile.

        Parameters
        ----------
        tile : ``BufferedTile``
            another tile
        """
        return [
            self.tile(*intersecting_tile.id)
            for intersecting_tile in self.tile_pyramid.intersecting(tile)
        ]


Instruction:
How would you code a function in Python 3 to
return dictionary representation of pyramid parameters.

Response:
def to_dict(self):
        """
        Return dictionary representation of pyramid parameters.
        """
        return dict(
            grid=self.grid.to_dict(),
            metatiling=self.metatiling,
            tile_size=self.tile_size,
            pixelbuffer=self.pixelbuffer
        )


Instruction:
Write a Python 3 script for
getting the children of this tile.

Response:
def get_children(self):
        """
        Get tile children (intersecting tiles in next zoom level).

        Returns
        -------
        children : list
            a list of ``BufferedTiles``
        """
        return [BufferedTile(t, self.pixelbuffer) for t in self._tile.get_children()]


Instruction:
Can you create a Python 3 function that
returns list of BufferedTiles that are connected to the current tile.

Response:
def get_neighbors(self, connectedness=8):
        """
        Return tile neighbors.

        Tile neighbors are unique, i.e. in some edge cases, where both the left
        and right neighbor wrapped around the antimeridian is the same. Also,
        neighbors ouside the northern and southern TilePyramid boundaries are
        excluded, because they are invalid.

        -------------
        | 8 | 1 | 5 |
        -------------
        | 4 | x | 2 |
        -------------
        | 7 | 3 | 6 |
        -------------

        Parameters
        ----------
        connectedness : int
            [4 or 8] return four direct neighbors or all eight.

        Returns
        -------
        list of BufferedTiles
        """
        return [
            BufferedTile(t, self.pixelbuffer)
            for t in self._tile.get_neighbors(connectedness=connectedness)
        ]


Instruction:
Make a summary of the following Python 3 code
def is_on_edge(self):
        return (
            self.left <= self.tile_pyramid.left or      # touches_left
            self.bottom <= self.tile_pyramid.bottom or  # touches_bottom
            self.right >= self.tile_pyramid.right or    # touches_right
            self.top >= self.tile_pyramid.top           # touches_top
        )

Response: Determine whether tile touches or goes over pyramid edge.


Instruction:
Make a summary of the following Python 3 code
def execute(
    mp,
    resampling="nearest",
    scale_method=None,
    scales_minmax=None
):
    """
    Read, stretch and return raster data.

    Inputs:
    -------
    raster
        raster file

    Parameters:
    -----------
    resampling : str
        rasterio.Resampling method
    scale_method : str
        - dtype_scale: use dtype minimum and maximum values
        - minmax_scale: use dataset bands minimum and maximum values
        - crop: clip data to output dtype
    scales_minmax : tuple
        tuple of band specific scale values

    Output:
    -------
    np.ndarray
    """
    with mp.open("raster", resampling=resampling) as raster_file:

        # exit if input tile is empty
        if raster_file.is_empty():
            return "empty"

        # actually read data and iterate through bands
        scaled = ()
        mask = ()
        raster_data = raster_file.read()
        if raster_data.ndim == 2:
            raster_data = ma.expand_dims(raster_data, axis=0)
        if not scale_method:
            scales_minmax = [(i, i) for i in range(len(raster_data))]

        for band, (scale_min, scale_max) in zip(raster_data, scales_minmax):
            if scale_method in ["dtype_scale", "minmax_scale"]:
                scaled += (_stretch_array(band, scale_min, scale_max), )
            elif scale_method == "crop":
                scaled += (np.clip(band, scale_min, scale_max), )
            else:
                scaled += (band, )
            mask += (band.mask, )

    return ma.masked_array(np.stack(scaled), np.stack(mask))

Response: Execute the raster file read stretch and return raster data.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def read(self, output_tile, **kwargs):
        try:
            return read_raster_no_crs(self.get_path(output_tile))
        except FileNotFoundError:
            return self.empty(output_tile)

Response: Read existing process output.


Instruction:
Implement a function in Python 3 to
write data from process_tile to GeoTIFF file.

Response:
def write(self, process_tile, data):
        """
        Write data from process tiles into GeoTIFF file(s).

        Parameters
        ----------
        process_tile : ``BufferedTile``
            must be member of process ``TilePyramid``
        data : ``np.ndarray``
        """
        if (
            isinstance(data, tuple) and
            len(data) == 2 and
            isinstance(data[1], dict)
        ):
            data, tags = data
        else:
            tags = {}
        data = prepare_array(
            data,
            masked=True,
            nodata=self.nodata,
            dtype=self.profile(process_tile)["dtype"]
        )

        if data.mask.all():
            logger.debug("data empty, nothing to write")
        else:
            # in case of S3 output, create an boto3 resource
            bucket_resource = get_boto3_bucket(self._bucket) if self._bucket else None

            # Convert from process_tile to output_tiles and write
            for tile in self.pyramid.intersecting(process_tile):
                out_path = self.get_path(tile)
                self.prepare_path(tile)
                out_tile = BufferedTile(tile, self.pixelbuffer)
                write_raster_window(
                    in_tile=process_tile,
                    in_data=data,
                    out_profile=self.profile(out_tile),
                    out_tile=out_tile,
                    out_path=out_path,
                    tags=tags,
                    bucket_resource=bucket_resource
                )


Instruction:
Given the following Python 3 function, write the documentation
def profile(self, tile=None):
        dst_metadata = GTIFF_DEFAULT_PROFILE
        dst_metadata.pop("transform", None)
        dst_metadata.update(
            count=self.output_params["bands"],
            dtype=self.output_params["dtype"],
            driver="GTiff"
        )
        if tile is not None:
            dst_metadata.update(
                crs=tile.crs, width=tile.width, height=tile.height,
                affine=tile.affine)
        else:
            for k in ["crs", "width", "height", "affine"]:
                dst_metadata.pop(k, None)
        if "nodata" in self.output_params:
            dst_metadata.update(nodata=self.output_params["nodata"])
        try:
            if "compression" in self.output_params:
                warnings.warn(
                    DeprecationWarning("use 'compress' instead of 'compression'")
                )
                dst_metadata.update(compress=self.output_params["compression"])
            else:
                dst_metadata.update(compress=self.output_params["compress"])
            dst_metadata.update(predictor=self.output_params["predictor"])
        except KeyError:
            pass
        return dst_metadata

Response: Create a dictionary of dictionary of dictionary of dictionary of image data.


Instruction:
Write a Python 3 script for
returning an empty array.

Response:
def empty(self, process_tile):
        """
        Return empty data.

        Parameters
        ----------
        process_tile : ``BufferedTile``
            must be member of process ``TilePyramid``

        Returns
        -------
        empty data : array
            empty array with data type provided in output profile
        """
        profile = self.profile(process_tile)
        return ma.masked_array(
            data=np.full(
                (profile["count"], ) + process_tile.shape, profile["nodata"],
                dtype=profile["dtype"]),
            mask=True
        )


Instruction:
Make a summary of the following Python 3 code
def for_web(self, data):
        return memory_file(
            prepare_array(
                data, masked=True, nodata=self.nodata, dtype=self.profile()["dtype"]
            ),
            self.profile()
        ), "image/tiff"

Response: Convert data to web output.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def open(self, tile, process, **kwargs):
        return InputTile(tile, process, kwargs.get("resampling", None))

Response: Open process output as input for other process.


Instruction:
Implement a Python 3 function for
reading reprojected & resampled input data.

Response:
def read(self, indexes=None, **kwargs):
        """
        Read reprojected & resampled input data.

        Parameters
        ----------
        indexes : integer or list
            band number or list of band numbers

        Returns
        -------
        data : array
        """
        band_indexes = self._get_band_indexes(indexes)
        arr = self.process.get_raw_output(self.tile)
        if len(band_indexes) == 1:
            return arr[band_indexes[0] - 1]
        else:
            return ma.concatenate([ma.expand_dims(arr[i - 1], 0) for i in band_indexes])


Instruction:
Create a Python 3 function for
checking if there is data within this tile.

Response:
def is_empty(self, indexes=None):
        """
        Check if there is data within this tile.

        Returns
        -------
        is empty : bool
        """
        # empty if tile does not intersect with file bounding box
        return not self.tile.bbox.intersects(self.process.config.area_at_zoom())


Instruction:
Explain what the following Python 3 code does
def _get_band_indexes(self, indexes=None):
        if indexes:
            if isinstance(indexes, list):
                return indexes
            else:
                return [indexes]
        else:
            return range(1, self.process.config.output.profile(self.tile)["count"] + 1)

Response: Return valid band indexes.


Instruction:
Can you implement a function in Python 3 that
creates a dictionary of metadata for rasterio.

Response:
def profile(self, tile=None):
        """
        Create a metadata dictionary for rasterio.

        Parameters
        ----------
        tile : ``BufferedTile``

        Returns
        -------
        metadata : dictionary
            output profile dictionary used for rasterio.
        """
        dst_metadata = PNG_DEFAULT_PROFILE
        dst_metadata.pop("transform", None)
        if tile is not None:
            dst_metadata.update(
                width=tile.width, height=tile.height, affine=tile.affine,
                crs=tile.crs)
        try:
            dst_metadata.update(count=self.output_params["count"])
        except KeyError:
            pass
        return dst_metadata


Instruction:
Can you implement a function in Python 3 that
converts data to web output.

Response:
def for_web(self, data):
        """
        Convert data to web output.

        Parameters
        ----------
        data : array

        Returns
        -------
        web data : array
        """
        rgba = self._prepare_array_for_png(data)
        data = ma.masked_where(rgba == self.nodata, rgba)
        return memory_file(data, self.profile()), 'image/png'


Instruction:
Can you create a Python 3 function that
returns empty data. Parameters ---------- process_tile : ``BufferedTile`` must be member of process ``TilePyramid`` Returns ------- empty data : array empty array with data type given in output parameters

Response:
def empty(self, process_tile):
        """
        Return empty data.

        Parameters
        ----------
        process_tile : ``BufferedTile``
            must be member of process ``TilePyramid``

        Returns
        -------
        empty data : array
            empty array with data type given in output parameters
        """
        bands = (
            self.output_params["bands"]
            if "bands" in self.output_params
            else PNG_DEFAULT_PROFILE["count"]
        )
        return ma.masked_array(
            data=ma.zeros((bands, ) + process_tile.shape),
            mask=ma.zeros((bands, ) + process_tile.shape),
            dtype=PNG_DEFAULT_PROFILE["dtype"]
        )


Instruction:
How would you implement a function in Python 3 that
serves a Mapchete process.

Response:
def serve(
    mapchete_file,
    port=None,
    internal_cache=None,
    zoom=None,
    bounds=None,
    overwrite=False,
    readonly=False,
    memory=False,
    input_file=None,
    debug=False,
    logfile=None
):
    """
    Serve a Mapchete process.

    Creates the Mapchete host and serves both web page with OpenLayers and the
    WMTS simple REST endpoint.
    """
    app = create_app(
        mapchete_files=[mapchete_file], zoom=zoom,
        bounds=bounds, single_input_file=input_file,
        mode=_get_mode(memory, readonly, overwrite), debug=debug
    )
    if os.environ.get("MAPCHETE_TEST") == "TRUE":
        logger.debug("don't run flask app, MAPCHETE_TEST environment detected")
    else:
        app.run(
            threaded=True, debug=True, port=port, host='0.0.0.0',
            extra_files=[mapchete_file]
        )


Instruction:
Explain what the following Python 3 code does
def create_app(
    mapchete_files=None, zoom=None, bounds=None, single_input_file=None,
    mode="continue", debug=None
):
    """Configure and create Flask app."""
    from flask import Flask, render_template_string
    app = Flask(__name__)
    mapchete_processes = {
        os.path.splitext(os.path.basename(mapchete_file))[0]: mapchete.open(
            mapchete_file, zoom=zoom, bounds=bounds,
            single_input_file=single_input_file, mode=mode, with_cache=True,
            debug=debug)
        for mapchete_file in mapchete_files
    }

    mp = next(iter(mapchete_processes.values()))
    pyramid_type = mp.config.process_pyramid.grid
    pyramid_srid = mp.config.process_pyramid.crs.to_epsg()
    process_bounds = ",".join([str(i) for i in mp.config.bounds_at_zoom()])
    grid = "g" if pyramid_srid == 3857 else "WGS84"
    web_pyramid = BufferedTilePyramid(pyramid_type)

    @app.route('/', methods=['GET'])
    def index():
        """Render and hosts the appropriate OpenLayers instance."""
        return render_template_string(
            pkgutil.get_data(
                'mapchete.static', 'index.html').decode("utf-8"),
            srid=pyramid_srid,
            process_bounds=process_bounds,
            is_mercator=(pyramid_srid == 3857),
            process_names=mapchete_processes.keys()
        )

    @app.route(
        "/".join([
            "", "wmts_simple", "1.0.0", "<string:mp_name>", "default",
            grid, "<int:zoom>", "<int:row>", "<int:col>.<string:file_ext>"]),
        methods=['GET'])
    def get(mp_name, zoom, row, col, file_ext):
        """Return processed, empty or error (in pink color) tile."""
        logger.debug(
            "received tile (%s, %s, %s) for process %s", zoom, row, col,
            mp_name)
        # convert zoom, row, col into tile object using web pyramid
        return _tile_response(
            mapchete_processes[mp_name], web_pyramid.tile(zoom, row, col),
            debug)

    return app

Response: Configure and create Flask app.


Instruction:
Can you write a function in Python 3 where it
reads a window of raster files from a single file.

Response:
def read_raster_window(
    input_files,
    tile,
    indexes=None,
    resampling="nearest",
    src_nodata=None,
    dst_nodata=None,
    gdal_opts=None
):
    """
    Return NumPy arrays from an input raster.

    NumPy arrays are reprojected and resampled to tile properties from input
    raster. If tile boundaries cross the antimeridian, data on the other side
    of the antimeridian will be read and concatenated to the numpy array
    accordingly.

    Parameters
    ----------
    input_files : string or list
        path to a raster file or list of paths to multiple raster files readable by
        rasterio.
    tile : Tile
        a Tile object
    indexes : list or int
        a list of band numbers; None will read all.
    resampling : string
        one of "nearest", "average", "bilinear" or "lanczos"
    src_nodata : int or float, optional
        if not set, the nodata value from the source dataset will be used
    dst_nodata : int or float, optional
        if not set, the nodata value from the source dataset will be used
    gdal_opts : dict
        GDAL options passed on to rasterio.Env()

    Returns
    -------
    raster : MaskedArray
    """
    with rasterio.Env(
        **get_gdal_options(
            gdal_opts,
            is_remote=path_is_remote(
                input_files[0] if isinstance(input_files, list) else input_files, s3=True
            )
        )
    ) as env:
        logger.debug("reading %s with GDAL options %s", input_files, env.options)
        return _read_raster_window(
            input_files,
            tile,
            indexes=indexes,
            resampling=resampling,
            src_nodata=src_nodata,
            dst_nodata=dst_nodata
        )


Instruction:
How would you code a function in Python 3 to
extract a numpy array from a raster file.

Response:
def _get_warped_array(
    input_file=None,
    indexes=None,
    dst_bounds=None,
    dst_shape=None,
    dst_crs=None,
    resampling=None,
    src_nodata=None,
    dst_nodata=None
):
    """Extract a numpy array from a raster file."""
    try:
        return _rasterio_read(
            input_file=input_file,
            indexes=indexes,
            dst_bounds=dst_bounds,
            dst_shape=dst_shape,
            dst_crs=dst_crs,
            resampling=resampling,
            src_nodata=src_nodata,
            dst_nodata=dst_nodata
        )
    except Exception as e:
        logger.exception("error while reading file %s: %s", input_file, e)
        raise


Instruction:
Write a Python 3 function that can
wrap function around rasterio. open. read.

Response:
def read_raster_no_crs(input_file, indexes=None, gdal_opts=None):
    """
    Wrapper function around rasterio.open().read().

    Parameters
    ----------
    input_file : str
        Path to file
    indexes : int or list
        Band index or list of band indexes to be read.

    Returns
    -------
    MaskedArray

    Raises
    ------
    FileNotFoundError if file cannot be found.
    """
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        try:
            with rasterio.Env(
                **get_gdal_options(
                    gdal_opts, is_remote=path_is_remote(input_file, s3=True)
                )
            ):
                with rasterio.open(input_file, "r") as src:
                    return src.read(indexes=indexes, masked=True)
        except RasterioIOError as e:
            for i in ("does not exist in the file system", "No such file or directory"):
                if i in str(e):
                    raise FileNotFoundError("%s not found" % input_file)
            else:
                raise


Instruction:
Write a Python 3 script for
writing a window from a numpy array to a GeoTIFF file.

Response:
def write_raster_window(
    in_tile=None, in_data=None, out_profile=None, out_tile=None, out_path=None,
    tags=None, bucket_resource=None
):
    """
    Write a window from a numpy array to an output file.

    Parameters
    ----------
    in_tile : ``BufferedTile``
        ``BufferedTile`` with a data attribute holding NumPy data
    in_data : array
    out_profile : dictionary
        metadata dictionary for rasterio
    out_tile : ``Tile``
        provides output boundaries; if None, in_tile is used
    out_path : string
        output path to write to
    tags : optional tags to be added to GeoTIFF file
    bucket_resource : boto3 bucket resource to write to in case of S3 output
    """
    if not isinstance(out_path, str):
        raise TypeError("out_path must be a string")
    logger.debug("write %s", out_path)
    if out_path == "memoryfile":
        raise DeprecationWarning(
            "Writing to memoryfile with write_raster_window() is deprecated. "
            "Please use RasterWindowMemoryFile."
        )
    out_tile = in_tile if out_tile is None else out_tile
    _validate_write_window_params(in_tile, out_tile, in_data, out_profile)

    # extract data
    window_data = extract_from_array(
        in_raster=in_data,
        in_affine=in_tile.affine,
        out_tile=out_tile
    ) if in_tile != out_tile else in_data

    # use transform instead of affine
    if "affine" in out_profile:
        out_profile["transform"] = out_profile.pop("affine")

    # write if there is any band with non-masked data
    if window_data.all() is not ma.masked:

        try:
            if out_path.startswith("s3://"):
                with RasterWindowMemoryFile(
                    in_tile=out_tile,
                    in_data=window_data,
                    out_profile=out_profile,
                    out_tile=out_tile,
                    tags=tags
                ) as memfile:
                    logger.debug((out_tile.id, "upload tile", out_path))
                    bucket_resource.put_object(
                        Key="/".join(out_path.split("/")[3:]),
                        Body=memfile
                    )
            else:
                with rasterio.open(out_path, 'w', **out_profile) as dst:
                    logger.debug((out_tile.id, "write tile", out_path))
                    dst.write(window_data.astype(out_profile["dtype"], copy=False))
                    _write_tags(dst, tags)
        except Exception as e:
            logger.exception("error while writing file %s: %s", out_path, e)
            raise
    else:
        logger.debug((out_tile.id, "array window empty", out_path))


Instruction:
Here you have a function in Python 3, explain what it does
def extract_from_array(in_raster=None, in_affine=None, out_tile=None):
    if isinstance(in_raster, ReferencedRaster):
        in_affine = in_raster.affine
        in_raster = in_raster.data

    # get range within array
    minrow, maxrow, mincol, maxcol = bounds_to_ranges(
        out_bounds=out_tile.bounds, in_affine=in_affine, in_shape=in_raster.shape
    )
    # if output window is within input window
    if (
        minrow >= 0 and
        mincol >= 0 and
        maxrow <= in_raster.shape[-2] and
        maxcol <= in_raster.shape[-1]
    ):
        return in_raster[..., minrow:maxrow, mincol:maxcol]
    # raise error if output is not fully within input
    else:
        raise ValueError("extraction fails if output shape is not within input")

Response: Extract raster data window array.