Skip to content

extent

Classes:

  • Extent

    Geographic extent.

Extent

Extent(*args, srs: srs_input = 'latlon')

Geographic extent.

The Extent object represents geographic extents of an area and exposes useful methods which depend on those extents. This includes: - Easily representing the boundaries as (xMin, xMax, yMin, yMax) or (xMin, yMin, xMax, yMax) - Casting to another projection system - Padding and shifting the boundaries - "Fitting" the boundaries onto a given resolution - Clipping a given raster file

Initialization:
  • Extent(xMin, yMin, xMax, yMax [, srs])
  • Extent.from_xyXY( (xMin, yMin, xMax, yMax) [, srs])
  • Extent.from_xXyY( (xMin, xMax, yMin, yMax) [, srs])
  • Extent.fromGeom( geom [, srs] )
  • Extent.fromVector( vector-file-path )
  • Extent.fromRaster( raster-file-path )
  • Extent.load( args )

Create extent from explicitly defined boundaries.

Usage:

Extent(xMin, yMin, xMax, yMax [, srs=]) Extent( (xMin, yMin, xMax, yMax) [, srs=])

Where: xMin - The minimal x value in the respective SRS yMin - The minimal y value in the respective SRS xMax - The maximal x value in the respective SRS yMax - The maximal y value in the respective SRS srs - The Spatial Reference system to use

Methods:

  • castTo

    Creates a new Extent by transforming an extent from the original Extent's

  • center

    Get the Extent's center.

  • clipRaster

    Clip a given raster source to the calling Extent.

  • computePixelSize

    Finds the pixel resolution which fits to the Extent for a given pixel count.

  • contains

    Tests if the extent contains another given extent.

  • containsLoc

    Test if the extent contains a location or an iterable of locations.

  • contoursFromRaster

    Convenience wrapper for geokit.raster.contours which automatically

  • corners

    Returns the four corners of the extent as ogr.gGometry points or as (x,y)

  • createRaster

    Convenience function for geokit.raster.createRaster which sets 'bounds'

  • drawSmopyMap

    Draws a basemap using the "smopy" python package.

  • exportWKT

    Export the extent to a Well-Known_Text string.

  • extractFeatures

    Convenience wrapper for geokit.vector.extractFeatures() by setting the

  • extractMatrix

    Convenience wrapper around geokit.raster.extractMatrix(). Extracts the

  • filterSources

    Filter a list of sources by those whose's envelope overlaps the Extent.

  • findWithin

    Finds the indexes of the given extent within the main extent according

  • fit

    Fit the extent to a given pixel resolution.

  • fitsResolution

    Test if calling Extent first around the given unit(s) (at least within

  • fromGeom

    Create extent around a given geometry.

  • fromLocationSet

    Create extent around the contents of a LocationSet object.

  • fromRaster

    Create extent around the contents of a raster source.

  • fromTile

    Generates an Extent corresponding to tiles used for "slippery maps".

  • fromTileAt

    Generates an Extent corresponding to tiles used for "slippery maps"

  • fromVector

    Create extent around the contemts of a vector source.

  • fromWKT

    Create extent from a Well-Known_Text string.

  • from_xXyY

    Create an Extent from explicitly defined boundaries.

  • inSourceExtent

    Tests if the extent box is at least partially contained in the extent-box

  • load

    Attempts to load an Extent from a variety of inputs in the most

  • mutateRaster

    Convenience function for geokit.raster.mutateRaster which automatically

  • mutateVector

    Convenience function for geokit.vector.mutateVector which automatically

  • overlaps

    Tests if the extent overlaps with another given extent.

  • pad

    Pad the extent in all directions.

  • rasterMosaic

    Create a raster source surrounding the Extent from a collection of other rasters.

  • rasterize

    Convenience function for geokit.vector.rasterize() which automatically

  • shift

    Shift the extent in the X and/or Y dimensions.

  • subTiles

    Generates tile Extents at a given zoom level which encompass the invoking Extent.

  • tileBox

    Determine the tile Extent at a given zoom level which surround the invoked Extent.

  • tileIndexBox

    Determine the tile indexes at a given zoom level which surround the invoked Extent.

  • tileMosaic

    Create a raster source surrounding the Extent from a collection of tiles.

  • tileSources

    Get the tiles sources which contribute to the invoking Extent.

  • warp

    Convenience function for geokit.raster.warp() which automatically sets the

Attributes:

  • YxyX (tuple[float, float, float, float]) –

    Returns a tuple of the extent boundaries in order:

  • box

    Returns a rectangular ogr.Geometry object representing the extent.

  • xXyY (tuple[float, float, float, float]) –

    Returns a tuple of the extent boundaries in order:

  • xYXy (tuple[float, float, float, float]) –

    Returns a tuple of the extent boundaries in order:

  • xlim (tuple[float, float]) –

    Returns a tuple of the x-axis extent boundaries in order:

  • xyXY (tuple[float, float, float, float]) –

    Returns a tuple of the extent boundaries in order:

  • ylim (tuple[float, float]) –

    Returns a tuple of the y-axis extent boundaries in order:

  • yxYX (tuple[float, float, float, float]) –

    Returns a tuple of the extent boundaries in order:

Source code in geokit/core/extent.py
def __init__(self, *args, srs: srs_input = "latlon"):
    """Create extent from explicitly defined boundaries.

    Usage:
    ------
    Extent(xMin, yMin, xMax, yMax [, srs=<srs>])
    Extent( (xMin, yMin, xMax, yMax) [, srs=<srs>])

    Where:
        xMin - The minimal x value in the respective SRS
        yMin - The minimal y value in the respective SRS
        xMax - The maximal x value in the respective SRS
        yMax - The maximal y value in the respective SRS
        srs - The Spatial Reference system to use
    """
    # Unpack args
    if len(args) == 1:
        xMin, yMin, xMax, yMax = args[0]
    elif len(args) == 4:
        xMin, yMin, xMax, yMax = args
    else:
        raise GeoKitExtentError(
            "Incorrect number of positional arguments given in init (accepts 1 or 4). Is an srs given as 'srs=...'?"
        )

    # Ensure good inputs
    xMin, xMax = min(xMin, xMax), max(xMin, xMax)
    yMin, yMax = min(yMin, yMax), max(yMin, yMax)

    self.xMin = xMin
    self.xMax = xMax
    self.yMin = yMin
    self.yMax = yMax
    self.srs = SRS.loadSRS(srs)

    self._box = GEOM.box(self.xMin, self.yMin, self.xMax, self.yMax, srs=self.srs)

YxyX property

YxyX: tuple[float, float, float, float]

Returns a tuple of the extent boundaries in order: yMax, xMin, yMin, xMax.

box property

box

Returns a rectangular ogr.Geometry object representing the extent.

xXyY property

xXyY: tuple[float, float, float, float]

Returns a tuple of the extent boundaries in order: xMin, xMax, yMin, yMax.

xYXy property

xYXy: tuple[float, float, float, float]

Returns a tuple of the extent boundaries in order: xMin, yMax, xMax, yMin.

xlim property

xlim: tuple[float, float]

Returns a tuple of the x-axis extent boundaries in order: xMin, xMax.

xyXY property

xyXY: tuple[float, float, float, float]

Returns a tuple of the extent boundaries in order: xMin, yMin, xMax, yMax.

ylim property

ylim: tuple[float, float]

Returns a tuple of the y-axis extent boundaries in order: yMin, yMax.

yxYX property

yxYX: tuple[float, float, float, float]

Returns a tuple of the extent boundaries in order: yMin, xMin, yMax, xMax.

castTo

castTo(srs: srs_input, segments: numeric = 100)

Creates a new Extent by transforming an extent from the original Extent's srs to a target SRS.

Note:

The resulting region spanned by the extent will be equal-to or (almost certainly) larger than the original

Parameters:

  • srs

    (Anything acceptable to geokit.srs.loadSRS()) –

    The srs to cast the Extent object to

Returns:

Source code in geokit/core/extent.py
def castTo(self, srs: srs_input, segments: numeric = 100):
    """
    Creates a new Extent by transforming an extent from the original Extent's
    srs to a target SRS.

    Note:
    -----
    The resulting region spanned by the extent will be equal-to or (almost
    certainly) larger than the original

    Parameters
    ----------
    srs : Anything acceptable to geokit.srs.loadSRS()
        The srs to cast the Extent object to

    Returns
    -------
    Extent
    """
    srs = SRS.loadSRS(srs)

    if srs.IsSame(self.srs):
        return self

    segment_size = min(self.xMax - self.xMin, self.yMax - self.yMin) / segments
    box = self.box
    box.Segmentize(segment_size)
    box = GEOM.transform(box, toSRS=srs)
    xMin, xMax, yMin, yMax = box.GetEnvelope()
    return Extent(xMin, yMin, xMax, yMax, srs=srs)

center

center(srs=None)

Get the Extent's center.

Source code in geokit/core/extent.py
def center(self, srs=None):
    """Get the Extent's center."""
    x, y = (self.xMax + self.xMin) / 2, (self.yMax + self.yMin) / 2
    if not srs is None:
        srs = SRS.loadSRS(srs)
        if not srs.IsSame(self.srs):
            xy = SRS.xyTransform(x, y, fromSRS=self.srs, toSRS=srs, outputFormat="xy")

            x = xy.x
            y = xy.y
    return x, y

clipRaster

clipRaster(
    source, output: None | str = None, **kwargs
) -> None | Dataset

Clip a given raster source to the calling Extent.

Parameters:

  • source

    (Anything acceptable to geokit.raster.loadRaster()) –

    The source to clip

  • **kwargs

    All other keyword arguments are passed to gdal.Translate

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def clipRaster(self, source, output: None | str = None, **kwargs) -> None | gdal.Dataset:
    """Clip a given raster source to the calling Extent.

    Parameters
    ----------
    source : Anything acceptable to geokit.raster.loadRaster()
        The source to clip

    **kwargs:
        All other keyword arguments are passed to gdal.Translate

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    from time import time_ns

    opts = gdal.TranslateOptions(
        projWin=[self.xMin, self.yMax, self.xMax, self.yMin],
        projWinSRS=self.srs,
        **kwargs,
    )

    if output is None:
        fname = "/vsimem/clip_{}.tif".format(time_ns())
    else:
        fname = output
    ds = gdal.Translate(fname, source, options=opts)

    if output is None:
        return ds
    else:
        return output

computePixelSize

computePixelSize(*args)

Finds the pixel resolution which fits to the Extent for a given pixel count.

Note:
  • If only one integer argument is given, it is assumed to fit to both the X and Y dimensions
  • If two integer arguments are given, it is assumed to be in the order X then Y

Returns:

  • tuple -> (pixelWidth, pixelHeight)
Source code in geokit/core/extent.py
def computePixelSize(self, *args):
    """Finds the pixel resolution which fits to the Extent for a given pixel count.

    Note:
    -----
    * If only one integer argument is given, it is assumed to fit to both the X and Y dimensions
    * If two integer arguments are given, it is assumed to be in the order X then Y

    Returns
    -------
        tuple -> (pixelWidth, pixelHeight)
    """
    if len(args) == 1:
        pixels_x = args[0]
        pixels_y = args[0]
    else:
        pixels_x, pixels_y = args

    pixelWidth = (self.xMax - self.xMin) / pixels_x
    pixelHeight = (self.yMax - self.yMin) / pixels_y

    return pixelWidth, pixelHeight

contains

contains(extent, res=None)

Tests if the extent contains another given extent.

Note:

If an optional resolution ('res') is given, the containment value is also dependent on whether or not the given extent fits within the larger extent AND is situated along the given resolution

Parameters:

  • extent

    (Extent) –

    The Extent object to test for containment

  • res

    (numeric or tuple, default: None ) –

    The X & Y resolution to enforce

Returns:

  • bool
Source code in geokit/core/extent.py
def contains(self, extent, res=None):
    """Tests if the extent contains another given extent.

    Note:
    -----
    If an optional resolution ('res') is given, the containment value is also
    dependent on whether or not the given extent fits within the larger extent
    AND is situated along the given resolution

    Parameters
    ----------
    extent : Extent
        The Extent object to test for containment

    res : numeric or tuple
        The X & Y resolution to enforce

    Returns
    -------
    bool
    """
    # test raw bounds
    if (
        not extent.srs.IsSame(self.srs)
        or extent.xMin < self.xMin
        or extent.yMin < self.yMin
        or extent.xMax > self.xMax
        or extent.yMax > self.yMax
    ):
        return False

    if res:
        # unpack resolution
        try:
            dx, dy = res
        except:
            dx, dy = res, res

        # Test for factor of resolutions
        thresh = dx / 1000
        if (
            (extent.xMin - self.xMin) % dx > thresh
            or (extent.yMin - self.yMin) % dy > thresh
            or (self.xMax - extent.xMax) % dx > thresh
            or (self.yMax - extent.yMax) % dy > thresh
        ):
            return False
    return True

containsLoc

containsLoc(locs)

Test if the extent contains a location or an iterable of locations.

Parameters:

  • locs

    (Anything acceptable to LocationSet()) –

    The locations to be checked

Returns:

  • * If a single location is checker: bool
  • * If multiple locations are checked: numpy.ndarray
Source code in geokit/core/extent.py
def containsLoc(
    self,
    locs,
):
    """Test if the extent contains a location or an iterable of locations.

    Parameters
    ----------
    locs : Anything acceptable to LocationSet()
        The locations to be checked

    Returns
    -------
    * If a single location is checker: bool
    * If multiple locations are checked: numpy.ndarray
    """
    self.box  # initialize the box

    # Normalize locations
    locs = LocationSet(locs).asXY(self.srs)

    # Do tests
    sel = np.ones(locs.shape[0], dtype=bool)
    sel *= locs[:, 0] >= self.xMin
    sel *= locs[:, 0] <= self.xMax
    sel *= locs[:, 1] >= self.yMin
    sel *= locs[:, 1] <= self.yMax

    # Done!
    if sel.size == 1:
        return sel[0]
    else:
        return sel

contoursFromRaster

contoursFromRaster(
    raster,
    contourEdges: list[float],
    transformGeoms: bool = True,
    **kwargs,
) -> DataFrame

Convenience wrapper for geokit.raster.contours which automatically clips a raster to the invoked Extent.

Parameters:

  • raster

    (The raster datasource to warp from) –
  • contourEdges

    (list[float]) –

    The edges to search for within the raster dataset * This parameter can be set as "None", in which case an additional argument should be given to specify how the edges should be determined - See the documentation of "GDALContourGenerateEx" - Ex. "LEVEL_INTERVAL=10", contourEdges=None

  • transformGeoms

    (bool, default: True ) –

    If True, geometries are transformed to the Extent's SRS, otherwise they are left in their native SRS

  • kwargs

    Keyword arguments to pass on to the contours function * See geokit.raster.contours

Returns:

  • DataFrame
  • With columns:

    'geom' -> The contiguous-valued geometries 'ID' -> The associated contour edge for each object

Source code in geokit/core/extent.py
def contoursFromRaster(
    self, raster, contourEdges: list[float], transformGeoms: bool = True, **kwargs
) -> pd.DataFrame:
    """Convenience wrapper for geokit.raster.contours which automatically
    clips a raster to the invoked Extent.

    Parameters
    ----------
    raster : The raster datasource to warp from

    contourEdges : list[float]
        The edges to search for within the raster dataset
        * This parameter can be set as "None", in which case an additional
            argument should be given to specify how the edges should be determined
            - See the documentation of "GDALContourGenerateEx"
            - Ex. "LEVEL_INTERVAL=10", contourEdges=None

    transformGeoms : bool
        If True, geometries are transformed to the Extent's SRS, otherwise they
        are left in their native SRS

    kwargs
        Keyword arguments to pass on to the contours function
        * See geokit.raster.contours

    Returns
    -------
    pandas.DataFrame

    With columns:
        'geom' -> The contiguous-valued geometries
        'ID' -> The associated contour edge for each object
    """
    pass
    raster = self.clipRaster(raster)
    geoms = RASTER.contours(raster, contourEdges, **kwargs)

    if transformGeoms:
        geoms.geom = GEOM.transform(geoms.geom, toSRS=self.srs)

    return geoms

corners

corners(asPoints=False)

Returns the four corners of the extent as ogr.gGometry points or as (x,y) coordinates in the extent's srs.

Source code in geokit/core/extent.py
def corners(self, asPoints=False):
    """Returns the four corners of the extent as ogr.gGometry points or as (x,y)
    coordinates in the extent's srs.
    """
    if asPoints:
        # Make corner points
        bl = GEOM.point(self.xMin, self.yMin, srs=self.srs)
        br = GEOM.point(self.xMax, self.yMin, srs=self.srs)
        tl = GEOM.point(self.xMin, self.yMax, srs=self.srs)
        tr = GEOM.point(self.xMax, self.yMax, srs=self.srs)

    else:
        # Make corner points
        bl = (self.xMin, self.yMin)
        br = (self.xMax, self.yMin)
        tl = (self.xMin, self.yMax)
        tr = (self.xMax, self.yMax)

    return (bl, br, tl, tr)

createRaster

createRaster(pixelWidth, pixelHeight, **kwargs)

Convenience function for geokit.raster.createRaster which sets 'bounds' and 'srs' inputs.

  • The input resolution MUST fit within the extent

Parameters:

  • pixelWidth

    (numeric) –

    The pixel width of the raster in units of the input srs * The keyword 'dx' can be used as well and will override anything given assigned to 'pixelWidth'

  • pixelHeight

    (numeric) –

    The pixel height of the raster in units of the input srs * The keyword 'dy' can be used as well and will override anything given assigned to 'pixelHeight'

  • **kwargs

    All other keyword arguments are passed on to geokit.raster.createRaster()

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def createRaster(self, pixelWidth, pixelHeight, **kwargs):
    """Convenience function for geokit.raster.createRaster which sets 'bounds'
    and 'srs' inputs.

    * The input resolution MUST fit within the extent

    Parameters
    ----------
    pixelWidth : numeric
        The pixel width of the raster in units of the input srs
        * The keyword 'dx' can be used as well and will override anything given
        assigned to 'pixelWidth'

    pixelHeight : numeric
        The pixel height of the raster in units of the input srs
        * The keyword 'dy' can be used as well and will override anything given
          assigned to 'pixelHeight'

    **kwargs:
        All other keyword arguments are passed on to geokit.raster.createRaster()

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    if not self.fitsResolution((pixelWidth, pixelHeight)):
        raise GeoKitExtentError("The given resolution does not fit to the Extent boundaries")
    return RASTER.createRaster(
        bounds=self.xyXY,
        pixelWidth=pixelWidth,
        pixelHeight=pixelHeight,
        srs=self.srs,
        **kwargs,
    )

drawSmopyMap

drawSmopyMap(
    zoom,
    tileserver="https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
    tilesize=256,
    maxtiles=100,
    ax=None,
    **kwargs,
)

Draws a basemap using the "smopy" python package.

  • See more details about smopy here: https://github.com/rossant/smopy

Returns:

  • namedtuple
    • .ax -> The axes draw on
    • .srs -> The SRS used when drawing (will always be EPSG 3857)
    • .bounds -> The boundaries of the drawn map
Source code in geokit/core/extent.py
def drawSmopyMap(
    self,
    zoom,
    tileserver="https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
    tilesize=256,
    maxtiles=100,
    ax=None,
    **kwargs,
):
    """
    Draws a basemap using the "smopy" python package.

    * See more details about smopy here: https://github.com/rossant/smopy

    Parameters
    ----------
        zoom : int
            The zoom level to draw (between 1-20)
            * I suggest starting low (e.g. 4), and zooming in until you find a level that suits your needs

        tileserver : string
            The tile server to use

        tilesize : int
            The pixel size of the tiles from 'tileserver'

        maxtiles : int
            The maximum tiles to use when drawing an image
            * Be careful to adhere to the usage conditions stated by your selected tileserver!

        ax : matplotlib.axes
            The matplotlib axes to draw on
            * If 'None', then one will be generated automatically

        kwargs
            All extra keyword arguments are passed on to matplotlib.ax.imshow

    Returns
    -------
        namedtuple
            * .ax     -> The axes draw on
            * .srs    -> The SRS used when drawing (will always be EPSG 3857)
            * .bounds -> The boundaries of the drawn map
    """
    return RASTER.drawSmopyMap(
        bounds=self.castTo(SRS.EPSG4326).xyXY,
        zoom=zoom,
        tileserver=tileserver,
        tilesize=tilesize,
        maxtiles=maxtiles,
        ax=ax,
        **kwargs,
    )

exportWKT

exportWKT(delimiter='|') -> str

Export the extent to a Well-Known_Text string.

  • Actually the will be two WKT strings separated by a "|" character
  • These correspond to "|"

Parameters:

  • delimiter

    (The delimiter which separates the two WKT sections, default: '|' ) –

Returns:

  • string
Source code in geokit/core/extent.py
def exportWKT(self, delimiter="|") -> str:
    """Export the extent to a Well-Known_Text string.

    * Actually the will be two WKT strings separated by a "|" character
    * These correspond to "<A Geometry WKT>|<an SRS WKT>"

    Parameters
    ----------
    delimiter : The delimiter which separates the two WKT sections

    Returns
    -------
    string
    """
    return "{}{}{}".format(self.box.ExportToWkt(), delimiter, self.srs.ExportToWkt())

extractFeatures

extractFeatures(source, **kwargs)

Convenience wrapper for geokit.vector.extractFeatures() by setting the 'geom' input to the extent's box.

Parameters:

  • source

    (str) –

    The path to the vector file to load

  • **kwargs

    All other keyword arguments are passed on to vector.extractFeatures()

Returns:

  • * If asPandas is True: pandas.DataFrame or pandas.Series
  • * If asPandas is False: generator
Source code in geokit/core/extent.py
def extractFeatures(self, source, **kwargs):
    """Convenience wrapper for geokit.vector.extractFeatures() by setting the
    'geom' input to the extent's box.

    Parameters
    ----------
    source : str
        The path to the vector file to load

    **kwargs:
        All other keyword arguments are passed on to vector.extractFeatures()

    Returns
    -------
    * If asPandas is True: pandas.DataFrame or pandas.Series
    * If asPandas is False: generator
    """
    return VECTOR.extractFeatures(source=source, geom=self._box, **kwargs)

extractMatrix

extractMatrix(source, strict=True, **kwargs)

Convenience wrapper around geokit.raster.extractMatrix(). Extracts the extent directly from the given raster source as a matrix around the Extent.

Note:

The called extent must fit somewhere within the raster's grid

Parameters:

  • source

    The raster source to be read

  • strict

    Whether or not to allow a returned value which does not fit to the given extent !! If this is set to False, it is STRONGLY recommended to also set the argument 'returnBounds' as True so that the new computed boundary can be known

  • **kwargs

    All keyword arguments are passed to geokit.raster.extractMatrix

Returns:

  • ndarray or tuple
    • See geokit.raster.extractMatrix
Source code in geokit/core/extent.py
def extractMatrix(self, source, strict=True, **kwargs):
    """Convenience wrapper around geokit.raster.extractMatrix(). Extracts the
    extent directly from the given raster source as a matrix around the Extent.

    Note:
    -----
    The called extent must fit somewhere within the raster's grid

    Parameters
    ----------
    source: gdal.Dataset or str
        The raster source to be read

    strict: bool; optional
        Whether or not to allow a returned value which does not fit to the
        given extent
        !! If this is set to False, it is STRONGLY recommended to also set the
           argument 'returnBounds' as True so that the new computed boundary
           can be known

    **kwargs
        All keyword arguments are passed to geokit.raster.extractMatrix

    Returns
    -------
    numpy.ndarray or tuple
        * See geokit.raster.extractMatrix
    """
    if strict:
        ri = RASTER.rasterInfo(source)
        if not self.srs.IsSame(ri.srs):
            raise GeoKitExtentError("Extent and source do not share an srs")
        if not Extent._fromInfo(ri).contains(self, (ri.dx, ri.dy)):
            raise GeoKitExtentError("Extent does not fit the raster's resolution")

    return RASTER.extractMatrix(source, bounds=self.xyXY, boundsSRS=self.srs, **kwargs)

filterSources

filterSources(sources, error_on_missing=True)

Filter a list of sources by those whose's envelope overlaps the Extent.

Note:

Creates a filter object which can be immediately iterated over, or else can be cast as a list

Parameters:

  • sources

    (list or str) –

    The sources to filter * An iterable of vector/raster sources * An iterable of paths pointing to vector/raster sources * A glob string which will generate a list of source paths - see glob.glob for more info

  • error_on_missing

    (bool, default: True ) –

    If True, then if a file path is given which does not exist, a RunTime error is raised. Otherwise a warning is given Only performs check when input is a string

Returns:

  • filter
Source code in geokit/core/extent.py
def filterSources(self, sources, error_on_missing=True):
    """Filter a list of sources by those whose's envelope overlaps the Extent.

    Note:
    -----
    Creates a filter object which can be immediately iterated over, or else
    can be cast as a list

    Parameters
    ----------
    sources : list or str
        The sources to filter
        * An iterable of vector/raster sources
        * An iterable of paths pointing to vector/raster sources
        * A glob string which will generate a list of source paths
            - see glob.glob for more info

    error_on_missing : bool, optional
        If True, then if a file path is given which does not exist, a RunTime
            error is raised. Otherwise a warning is given
        Only performs check when input is a string

    Returns
    -------
    filter
    """
    # create list of searchable files
    if isinstance(sources, str):
        _directoryList = glob(sources)
    else:
        _directoryList = sources

    # Ensure all files exist (only check if input is a string)
    directoryList = []
    for source in _directoryList:
        if isinstance(source, str) and not isfile(source):
            if error_on_missing:
                raise RuntimeError("Cannot find file: " + source)
            else:
                warnings.warn("Skipping missing file: " + source)
        else:
            directoryList.append(source)

    return filter(self.inSourceExtent, directoryList)

findWithin

findWithin(extent, res=100, yAtTop=True)

Finds the indexes of the given extent within the main extent according to the given resolution.

Note:
  • Use this to compute the index offsets and window sizes of a window within a raster dataset
  • The two extents MUST share the same SRS

Parameters:

  • extent

    (Extent) –

    The extent to find within the calling extent

  • res

    (numeric or tuple, default: 100 ) –

    A resolution to check containment on

  • yAtTop

    (bool; optional, default: True ) –

    Instructs the offsetting to begin from yMax instead of from yMin

Returns:

  • tuple -> (xOffset, yOffset, xWindowSize, yWindowSize)
Source code in geokit/core/extent.py
def findWithin(self, extent, res=100, yAtTop=True):
    """Finds the indexes of the given extent within the main extent according
    to the given resolution.

    Note:
    -----
    * Use this to compute the index offsets and window sizes of a window
      within a raster dataset
    * The two extents MUST share the same SRS

    Parameters
    ----------
    extent : Extent
        The extent to find within the calling extent

    res : numeric or tuple
        A resolution to check containment on

    yAtTop : bool; optional
        Instructs the offsetting to begin from yMax instead of from yMin

    Returns
    -------
        tuple -> (xOffset, yOffset, xWindowSize, yWindowSize)
    """
    # test srs
    if not self.srs.IsSame(extent.srs):
        raise GeoKitExtentError("extents are not of the same srs")

    # try to unpack the resolution
    try:
        dx, dy = res
    except:
        dx, dy = res, res

    # Get offsets
    tmpX = (extent.xMin - self.xMin) / dx
    xOff = int(np.round(tmpX))

    if yAtTop:
        tmpY = (self.yMax - extent.yMax) / dy
    else:
        tmpY = (extent.yMin - self.yMin) / dy
    yOff = int(np.round(tmpY))

    if not (np.isclose(xOff, tmpX) and np.isclose(yOff, tmpY)):
        raise GeoKitExtentError("The extents are not relatable on the given resolution")

    # Get window sizes
    tmpX = (extent.xMax - extent.xMin) / dx
    xWin = int(np.round(tmpX))

    tmpY = (extent.yMax - extent.yMin) / dy
    yWin = int(np.round(tmpY))

    if not (np.isclose(xWin, tmpX) and np.isclose(yWin, tmpY)):
        raise GeoKitExtentError("The extents are not relatable on the given resolution")

    # Done!
    return IndexSet(xOff, yOff, xWin, yWin, xOff + xWin, yOff + yWin)

fit

fit(unit, dtype=None, start_raster=None) -> Extent

Fit the extent to a given pixel resolution.

Note:

The extent is always expanded to fit onto the given unit

Parameters:

  • unit

    (numeric or tuple) –

    The unit value(s) to check * If numeric, a single value is assumed for both X and Y dim * If tuple, resolutions for both dimensions (x, y)

  • start_raster

    (str(left or right), default: None ) –

    If None passed, the extent will be centered on the shape with overlaps left and right depending on individual shape width and raster cell width. If 'left'/'right' passed, extent edges will be matching min/max longitude of shape.

  • dtype

    (Type or dtype, default: None ) –

    The final data type of the boundary values

Returns:

Source code in geokit/core/extent.py
def fit(self, unit, dtype=None, start_raster=None) -> "Extent":
    """Fit the extent to a given pixel resolution.

    Note:
    -----
    The extent is always expanded to fit onto the given unit

    Parameters
    ----------
    unit : numeric or tuple
        The unit value(s) to check
        * If numeric, a single value is assumed for both X and Y dim
        * If tuple, resolutions for both dimensions (x, y)

    start_raster : str ('left' or 'right')
        If None passed, the extent will be centered on the shape with overlaps left and right
        depending on individual shape width and raster cell width. If 'left'/'right' passed,
        extent edges will be matching min/max longitude of shape.

    dtype : Type or np.dtype
        The final data type of the boundary values

    Returns
    -------
    Extent
    """
    try:
        unitX, unitY = unit
    except:
        unitX, unitY = unit, unit

    # Look for bad sizes
    if unitX > self.xMax - self.xMin:
        raise GeoKitExtentError("Unit size is larger than extent width")
    if unitY > self.yMax - self.yMin:
        raise GeoKitExtentError("Unit size is larger than extent width")

    # Calculate new extent
    if start_raster == "left":
        newXMin = self.xMin
        newYMin = np.floor(self.yMin / unitY) * unitY
        newXMax = self.xMin + np.ceil((self.xMax - self.xMin) / unitX) * unitX
        newYMax = np.ceil(self.yMax / unitY) * unitY
    elif start_raster == "right":
        newXMin = self.xMax - np.ceil((self.xMax - self.xMin) / unitX) * unitX
        newYMin = np.floor(self.yMin / unitY) * unitY
        newXMax = self.xMax
        newYMax = np.ceil(self.yMax / unitY) * unitY
    elif start_raster == None:
        newXMin = np.floor(self.xMin / unitX) * unitX
        newYMin = np.floor(self.yMin / unitY) * unitY
        newXMax = np.ceil(self.xMax / unitX) * unitX
        newYMax = np.ceil(self.yMax / unitY) * unitY
    else:
        raise GeoKitExtentError(
            "start_raster parameter must be either 'left' or 'right' (or None). Process terminated."
        )

    # Done!
    if dtype is None or isinstance(unitX, dtype):
        return Extent(newXMin, newYMin, newXMax, newYMax, srs=self.srs)
    else:
        return Extent(
            dtype(newXMin),
            dtype(newYMin),
            dtype(newXMax),
            dtype(newYMax),
            srs=self.srs,
        )

fitsResolution

fitsResolution(unit, tolerance=1e-06)

Test if calling Extent first around the given unit(s) (at least within an error defined by 'tolerance').

Parameters:

  • unit

    (numeric or tuple) –

    The unit value(s) to check * If float, a single resolution value is assumed for both X and Y dim * If tuple, resolutions for both dimensions (x, y)

  • tolerance

    (float, default: 1e-06 ) –

    The tolerance to allow when comparing float values

Returns:

Examples:

>>> ex = Extent( 100, 100, 300, 500)
>>> ex.fitsResolution(25) # True!
>>> ex.fitsResolution( (25, 10) ) # True!
>>> ex.fitsResolution(33) # False!
>>> ex.fitsResolution( (25, 33) ) # False!
Source code in geokit/core/extent.py
def fitsResolution(self, unit, tolerance=1e-6):
    """Test if calling Extent first around the given unit(s) (at least within
    an error defined by 'tolerance').

    Parameters
    ----------
    unit : numeric or tuple
        The unit value(s) to check
        * If float, a single resolution value is assumed for both X and Y dim
        * If tuple, resolutions for both dimensions (x, y)

    tolerance : float
        The tolerance to allow when comparing float values

    Returns
    -------
    Extent

    Examples
    --------
    >>> ex = Extent( 100, 100, 300, 500)
    >>> ex.fitsResolution(25) # True!
    >>> ex.fitsResolution( (25, 10) ) # True!
    >>> ex.fitsResolution(33) # False!
    >>> ex.fitsResolution( (25, 33) ) # False!
    """
    try:
        unitX, unitY = unit
    except:
        unitX, unitY = unit, unit

    xSteps = (self.xMax - self.xMin) / unitX
    xResidual = abs(xSteps - np.round(xSteps))
    if xResidual > tolerance:
        return False

    ySteps = (self.yMax - self.yMin) / unitY
    yResidual = abs(ySteps - np.round(ySteps))
    if yResidual > tolerance:
        return False

    return True

fromGeom staticmethod

fromGeom(geom) -> Extent

Create extent around a given geometry.

Parameters:

  • geom

    (Geometry) –

    The geometry from which to extract the extent

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromGeom(geom) -> "Extent":
    """Create extent around a given geometry.

    Parameters
    ----------
    geom : ogr.Geometry
        The geometry from which to extract the extent

    Returns
    -------
    Extent
    """
    # Read Envelope
    xMin, xMax, yMin, yMax = geom.GetEnvelope()

    # Done!
    return Extent(xMin, yMin, xMax, yMax, srs=geom.GetSpatialReference())

fromLocationSet staticmethod

fromLocationSet(locs) -> Extent

Create extent around the contents of a LocationSet object.

Parameters:

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromLocationSet(locs) -> "Extent":
    """Create extent around the contents of a LocationSet object.

    Parameters
    ----------
    locs : LocationSet

    Returns
    -------
    Extent
    """
    lonMin, latMin, lonMax, latMax = locs.getBounds()
    return Extent(lonMin, latMin, lonMax, latMax, srs=SRS.EPSG4326)

fromRaster staticmethod

fromRaster(source)

Create extent around the contents of a raster source.

Parameters:

  • source

    (Anything acceptable by loadRaster()) –

    The vector datasource to read from

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromRaster(source):
    """Create extent around the contents of a raster source.

    Parameters
    ----------
    source : Anything acceptable by loadRaster()
        The vector datasource to read from

    Returns
    -------
    Extent
    """
    dsInfo = RASTER.rasterInfo(source)

    xMin, yMin, xMax, yMax = dsInfo.bounds

    return Extent(xMin, yMin, xMax, yMax, srs=dsInfo.srs)

fromTile staticmethod

fromTile(xi: int, yi: int, zoom: int) -> Extent

Generates an Extent corresponding to tiles used for "slippery maps".

Parameters:

  • xi

    (int) –

    The tile's X-index - Range depends on zoom value

  • yi

    (int) –

    The tile's Y-index - Range depends on zoom value

  • zoom

    (int) –

    The tile's zoom index - Range is between 0 and 18

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromTile(xi: int, yi: int, zoom: int) -> "Extent":
    """Generates an Extent corresponding to tiles used for "slippery maps".

    Parameters
    ----------
    xi : int
        The tile's X-index
        - Range depends on zoom value

    yi : int
        The tile's Y-index
        - Range depends on zoom value

    zoom : int
        The tile's zoom index
        - Range is between 0 and 18

    Returns
    -------
    geokit.Extent
    """
    tl = smopy.num2deg(xi - 0.0, yi + 1.0, zoom)[::-1]
    br = smopy.num2deg(xi + 1.0, yi - 0.0, zoom)[::-1]

    o = SRS.xyTransform([tl, br], fromSRS=SRS.EPSG4326, toSRS=SRS.EPSG3857, outputFormat="xy")
    assert isinstance(o, TransformedPointsXY)
    return Extent(o.x.min(), o.y.min(), o.x.max(), o.y.max(), srs=SRS.EPSG3857)

fromTileAt staticmethod

fromTileAt(x, y, zoom, srs) -> Extent

Generates an Extent corresponding to tiles used for "slippery maps" at the coordinates ('x','y') in the 'srs' reference system.

Parameters:

  • x

    (float) –

    The X coordinate to search for a tile around

  • y

    (float) –

    The Y coordinate to search for a tile around

  • zoom

    (int) –

    The tile's zoom index - Range is between 0 and 18

  • srs

    (anything acceptable to SRS.loadSRS) –

    The SRS of the given 'x' & 'y' coordinates

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromTileAt(x, y, zoom, srs) -> "Extent":
    """Generates an Extent corresponding to tiles used for "slippery maps"
    at the coordinates ('x','y') in the 'srs' reference system.

    Parameters
    ----------
    x : float
        The X coordinate to search for a tile around

    y : float
        The Y coordinate to search for a tile around

    zoom : int
        The tile's zoom index
        - Range is between 0 and 18

    srs : anything acceptable to SRS.loadSRS
        The SRS of the given 'x' & 'y' coordinates

    Returns
    -------
    geokit.Extent
    """
    t = SRS.tileIndexAt(x=x, y=y, zoom=zoom, srs=srs)

    return Extent.fromTile(t.xi, t.yi, t.zoom)

fromVector staticmethod

fromVector(
    source,
    where: str | None = None,
    geom: Geometry | None = None,
) -> Extent

Create extent around the contemts of a vector source.

Parameters:

  • source

    (Anything acceptable by loadVector()) –

    The vector datasource to read from

  • where

    (str; optional, default: None ) –

    An SQL-style filtering string * Can be used to filter the input source according to their attributes * For tips, see "http://www.gdal.org/ogr_sql.html" Ex: where="eye_color='Green' AND IQ>90"

  • geom

    (ogr.Geometry; optional, default: None ) –

    The geometry to search within * All features are extracted which touch this Geometry

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromVector(source, where: str | None = None, geom: ogr.Geometry | None = None) -> "Extent":
    """Create extent around the contemts of a vector source.

    Parameters
    ----------
    source : Anything acceptable by loadVector()
        The vector datasource to read from

    where : str; optional
        An SQL-style filtering string
        * Can be used to filter the input source according to their attributes
        * For tips, see "http://www.gdal.org/ogr_sql.html"
        Ex:
          where="eye_color='Green' AND IQ>90"

    geom : ogr.Geometry; optional
        The geometry to search within
        * All features are extracted which touch this Geometry

    Returns
    -------
    Extent
    """
    if where is None and geom is None:
        shapeDS = VECTOR.loadVector(source)

        shapeLayer = shapeDS.GetLayer()
        shapeSRS = shapeLayer.GetSpatialRef()

        xMin, xMax, yMin, yMax = shapeLayer.GetExtent()

        return Extent(xMin, yMin, xMax, yMax, srs=shapeSRS)
    else:
        geom = VECTOR.extractFeature(source=source, where=where, geom=geom, onlyGeom=True)
        return Extent.fromGeom(geom)

fromWKT staticmethod

fromWKT(wkt, delimiter='|') -> Extent

Create extent from a Well-Known_Text string.

  • Actually the input should be two WKT strings separated by a "|" character
  • These correspond to "|"

Parameters:

  • wkt

    (The string to be processed) –
  • delimiter

    (The delimiter which separates the two WKT sections, default: '|' ) –

Returns:

Source code in geokit/core/extent.py
@staticmethod
def fromWKT(wkt, delimiter="|") -> "Extent":
    """Create extent from a Well-Known_Text string.

    * Actually the input should be two WKT strings separated by a "|" character
    * These correspond to "<A Geometry WKT>|<an SRS WKT>"

    Parameters
    ----------
    wkt : The string to be processed

    delimiter : The delimiter which separates the two WKT sections

    Returns
    -------
    Extent
    """
    geomWKT, srsWKT = wkt.split(delimiter)
    srs = SRS.loadSRS(srsWKT)
    geom = GEOM.convertWKT(geomWKT, srs=srs)

    return Extent.fromGeom(geom)

from_xXyY staticmethod

from_xXyY(bounds, srs='latlon') -> Extent

Create an Extent from explicitly defined boundaries.

Parameters:

  • bounds

    (tuple) –

    The (xMin, xMax, yMin, yMax) values for the extent

  • srs

    (Anything acceptable to geokit.srs.loadSRS(); optional, default: 'latlon' ) –

    The srs of the input coordinates * If not given, lat/lon coordinates are assumed

Returns:

Source code in geokit/core/extent.py
@staticmethod
def from_xXyY(bounds, srs="latlon") -> "Extent":
    """Create an Extent from explicitly defined boundaries.

    Parameters
    ----------
    bounds : tuple
        The (xMin, xMax, yMin, yMax) values for the extent

    srs : Anything acceptable to geokit.srs.loadSRS(); optional
        The srs of the input coordinates
          * If not given, lat/lon coordinates are assumed

    Returns
    -------
    Extent
    """
    return Extent(bounds[0], bounds[2], bounds[1], bounds[3], srs=srs)

inSourceExtent

inSourceExtent(source)

Tests if the extent box is at least partially contained in the extent-box of the given vector or raster source.

Parameters:

  • sources

    (str) –

    The sources to test

Source code in geokit/core/extent.py
def inSourceExtent(self, source):
    """Tests if the extent box is at least partially contained in the extent-box
    of the given vector or raster source.

    Parameters
    ----------
    sources : str
        The sources to test
    """
    try:
        # cover the case that the source file is an empty or single-point vector = no extent possible
        _tmp = VECTOR.extractFeatures(source)
        if len(_tmp) == 1 and _tmp.geom.iloc[0].GetGeometryName() == "POINT":
            # we have a single point, add minimal tolerance in each direction to enable an extent
            tol = 0.00001
            sourceExtent = Extent(
                _tmp.geom.iloc[0].GetX() * (1 - tol),
                _tmp.geom.iloc[0].GetY() * (1 - tol),
                _tmp.geom.iloc[0].GetX() * (1 + tol),
                _tmp.geom.iloc[0].GetY() * (1 + tol),
            )
            return self.overlaps(sourceExtent)
        elif len(_tmp) == 0:
            # source is an empty vector file, overlap is not possible
            return False
        else:
            # fall back to normal path below in except
            raise Exception()
    except:
        sourceExtent = Extent.load(source)
        return self.overlaps(sourceExtent)

load staticmethod

load(source, **kwargs) -> Extent

Attempts to load an Extent from a variety of inputs in the most appropriate manner.

One Extent initializer (.fromXXX) is called depending on the inputs

source is LocationSet -> Extent.fromLocationSet( source )
source is ogr.Geometry -> Extent.fromGeom( source )
source is not a string: -> Extent(*source, **kwargs)
source is a string:
    First try: Extent.fromVector(source)
    Then try: Extent.fromRaster(source)

If none of the above works, an error is raised

Returns:

Source code in geokit/core/extent.py
@staticmethod
def load(source, **kwargs) -> "Extent":
    """Attempts to load an Extent from a variety of inputs in the most
    appropriate manner.

    One Extent initializer (.fromXXX) is called depending on the inputs

        source is LocationSet -> Extent.fromLocationSet( source )
        source is ogr.Geometry -> Extent.fromGeom( source )
        source is not a string: -> Extent(*source, **kwargs)
        source is a string:
            First try: Extent.fromVector(source)
            Then try: Extent.fromRaster(source)

    If none of the above works, an error is raised

    Returns
    -------
    Extent
    """
    if isinstance(source, Extent):
        return source
    elif isinstance(source, LocationSet):
        return Extent.fromLocationSet(source)
    elif isinstance(source, ogr.Geometry):
        return Extent.fromGeom(source)
    elif UTIL.isVector(source):
        return Extent.fromVector(source)
    elif UTIL.isRaster(source):
        return Extent.fromRaster(source)
    elif isinstance(source, str):
        return Extent.fromWKT(source)

    try:  # Maybe the source is an iterable giving xyXY
        vals = list(source)
        if len(vals) == 4:
            return Extent(vals, **kwargs)
    except:
        pass

    raise GeoKitExtentError("Could not load the source")

mutateRaster

mutateRaster(
    source: load_raster_input,
    pixelWidth: numeric | None = None,
    pixelHeight: numeric | None = None,
    matchContext: bool = False,
    warpArgs: dict | None = None,
    processor: Callable | None = None,
    resampleAlg: Literal[
        "near", "bilinear", "cubic", "average"
    ] = "bilinear",
    **mutateArgs,
)

Convenience function for geokit.raster.mutateRaster which automatically warps the raster to the extent's area and srs before mutating.

Note:

If this is called without any arguments except for a source, it serves to clip the raster source around the Extent, therefore performing the same function as Extent.warp(...) on an Extent which has been cast to the source's srs

Parameters:

  • source

    (Anything acceptable to geokit.raster.loadRaster()) –

    The source to mutate

  • pixelHeight

    (numeric, default: None ) –

    The pixel height (y-resolution) of the output raster

  • pixelWidth

    (numeric, default: None ) –

    The pixel width (x-resolution) of the output raster

  • matchContext

    (bool; optional, default: False ) –
    • If True, Warp to the Extent's boundaries and srs before mutating
      • pixelHeight and pixelWidth MUST be provided in this case
    • If False, only warp to the Extent's boundaries, but keep its srs and resolution intact
  • warpArgs

    (dict; optional, default: None ) –

    Arguments to apply to the warping step * See geokit.raster.warp()

  • processor

    (Callable | None, default: None ) –

    The function performing the mutation of the raster's data * The function will take single argument (a 2D numpy.ndarray) * The function must return a numpy.ndarray of the same size as the input * The return type must also be containable within a Float32 (int and boolean is okay) * See example in geokit.raster.mutateRaster for more info

  • resampleAlg

    (str; optional, default: 'bilinear' ) –

    The resampling algorithm to use while warping * Knowing which option to use can have significant impacts! * Options are: 'near', 'bilinear', 'cubic', 'average'

  • **kwargs

    All other keyword arguments are passed to geokit.vector.mutateVector

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def mutateRaster(
    self,
    source: load_raster_input,
    pixelWidth: numeric | None = None,
    pixelHeight: numeric | None = None,
    matchContext: bool = False,
    warpArgs: dict | None = None,
    processor: Callable | None = None,
    resampleAlg: Literal["near", "bilinear", "cubic", "average"] = "bilinear",
    **mutateArgs,
):
    """Convenience function for geokit.raster.mutateRaster which automatically
    warps the raster to the extent's area and srs before mutating.

    Note:
    -----
    If this is called without any arguments except for a source, it serves
    to clip the raster source around the Extent, therefore performing
    the same function as Extent.warp(...) on an Extent which has been cast
    to the source's srs

    Parameters
    ----------
    source : Anything acceptable to geokit.raster.loadRaster()
        The source to mutate

    pixelHeight : numeric
        The pixel height (y-resolution) of the output raster

    pixelWidth : numeric
        The pixel width (x-resolution) of the output raster

    matchContext : bool; optional
        * If True, Warp to the Extent's boundaries and srs before mutating
            - pixelHeight and pixelWidth MUST be provided in this case
        * If False, only warp to the Extent's boundaries, but keep its
          srs and resolution intact

    warpArgs : dict; optional
        Arguments to apply to the warping step
        * See geokit.raster.warp()

    processor - function; optional
        The function performing the mutation of the raster's data
        * The function will take single argument (a 2D numpy.ndarray)
        * The function must return a numpy.ndarray of the same size as the input
        * The return type must also be containable within a Float32 (int and
          boolean is okay)
        * See example in geokit.raster.mutateRaster for more info

    resampleAlg : str; optional
        The resampling algorithm to use while warping
        * Knowing which option to use can have significant impacts!
        * Options are: 'near', 'bilinear', 'cubic', 'average'

    **kwargs:
        All other keyword arguments are passed to geokit.vector.mutateVector

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    if warpArgs is None:
        warpArgs = {}

    if processor is None:  # We won't do a mutation without a processor, since everything else
        # can be handled by Warp. Therefore we pass on any 'output' that is
        # given to the warping stage, unless one was already given
        warpArgs["output"] = warpArgs.get("output", mutateArgs.get("output", None))

    # Warp the source
    # TODO: Should the warping be updated to use Extent.clipRaster???
    if matchContext:
        if pixelWidth is None or pixelHeight is None:
            raise GeoKitExtentError("pixelWidth and pixelHeight must be provided when matchContext is True")

        source = self.warp(
            source=source,
            resampleAlg=resampleAlg,
            pixelWidth=pixelWidth,
            pixelHeight=pixelWidth,
            strict=True,
            **warpArgs,
        )
    else:
        if not "srs" in mutateArgs:
            source = RASTER.loadRaster(source)
            srs = source.GetProjectionRef()

        ext = self.castTo(srs)
        source = ext.warp(
            source=source,
            resampleAlg=resampleAlg,
            pixelWidth=pixelWidth,
            pixelHeight=pixelWidth,
            strict=False,
            **warpArgs,
        )

    # mutate the source
    if not processor is None:
        return RASTER.mutateRaster(source, processor=processor, **mutateArgs)
    else:
        return source

mutateVector

mutateVector(source, matchContext=False, **kwargs)

Convenience function for geokit.vector.mutateVector which automatically sets 'srs' and 'geom' input to the Extent's srs and geometry.

Note:

If this is called without any arguments except for a source, it serves to clip the vector source around the extent

Parameters:

  • source

    (Anything acceptable to geokit.vector.loadVector()) –

    The source to clip

  • matchContext

    (bool; optional, default: False ) –
    • If True, transforms all geometries to the Extent's srs before mutating
    • If False, the Extent is cast to the source's srs, and all filtering and mutating happens in that context
  • **kwargs

    All other keyword arguments are passed to geokit.vector.mutateVector

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def mutateVector(self, source, matchContext=False, **kwargs):
    """Convenience function for geokit.vector.mutateVector which automatically
    sets 'srs' and 'geom' input to the Extent's srs and geometry.

    Note:
    -----
    If this is called without any arguments except for a source, it serves
    to clip the vector source around the extent

    Parameters
    ----------
    source : Anything acceptable to geokit.vector.loadVector()
        The source to clip

    matchContext : bool; optional
        * If True, transforms all geometries to the Extent's srs before
          mutating
        * If False, the Extent is cast to the source's srs, and all filtering
          and mutating happens in that context

    **kwargs:
        All other keyword arguments are passed to geokit.vector.mutateVector

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    # Get the working srs
    if not matchContext:
        vinfo = VECTOR.vectorInfo(source)
        ext = self.castTo(vinfo.srs)
    else:
        ext = self

    # mutate the source
    return VECTOR.mutateVector(source, srs=ext.srs, geom=ext._box, **kwargs)

overlaps

overlaps(extent, referenceSRS=EPSG4326)

Tests if the extent overlaps with another given extent.

Note:

If an optional resolution ('res') is given, the containment value is also dependent on whether or not the given extent fits within the larger extent AND is situated along the given resolution

Parameters:

  • extent

    (Extent) –

    The Extent object to test for containment

  • referenceSRS

    The spatial reference frame to do the comparison in * Can be 'self'

Returns:

  • bool
Source code in geokit/core/extent.py
def overlaps(self, extent, referenceSRS=SRS.EPSG4326):
    """Tests if the extent overlaps with another given extent.

    Note:
    -----
    If an optional resolution ('res') is given, the containment value is also
    dependent on whether or not the given extent fits within the larger extent
    AND is situated along the given resolution

    Parameters
    ----------
    extent : Extent
        The Extent object to test for containment

    referenceSRS
        The spatial reference frame to do the comparison in
        * Can be 'self'

    Returns
    -------
    bool
    """
    if referenceSRS != "self":
        self = self.castTo(referenceSRS)
    else:
        referenceSRS = self.srs
    extent = extent.castTo(referenceSRS)

    if self.box.Intersects(extent.box):
        return True
    if extent.box.Intersects(self.box):
        return True

    return False

pad

pad(pad, percent=False) -> Extent

Pad the extent in all directions.

Parameters:

  • pad

    (float) –

    The amount to pad in all directions * In units of the extent's srs * Can also accept a negative padding

  • percent

    (bool, default: False ) –

    If True, the padding values are understood to be a percentage of the unpadded extent

Returns:

Source code in geokit/core/extent.py
def pad(self, pad, percent=False) -> "Extent":
    """Pad the extent in all directions.

    Parameters
    ----------
    pad : float
        The amount to pad in all directions
        * In units of the extent's srs
        * Can also accept a negative padding

    percent : bool, optional
        If True, the padding values are understood to be a percentage of the
        unpadded extent

    Returns
    -------
    Extent
    """
    # Check for no input pads
    if pad is None:
        return self

    # try breaking apart by x and y component
    try:
        xpad, ypad = pad
    except:
        xpad = pad
        ypad = pad

    if percent:
        xpad = xpad / 100 * (self.xMax - self.xMin) / 2
        ypad = ypad / 100 * (self.yMax - self.yMin) / 2

    # Pad the extent
    return Extent(
        self.xMin - xpad,
        self.yMin - ypad,
        self.xMax + xpad,
        self.yMax + ypad,
        srs=self.srs,
    )

rasterMosaic

rasterMosaic(
    sources: list[load_raster_input],
    resampleAlg: Literal[
        "near", "bilinear", "cubic", "average"
    ] = "near",
    _warpKwargs={},
    _skipFiltering: bool = False,
)

Create a raster source surrounding the Extent from a collection of other rasters.

Parameters:

  • sources

    (list, or something acceptable to gk.Extent.filterSources) –

    The sources to add together over the invoking Extent

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def rasterMosaic(
    self,
    sources: list[load_raster_input],
    resampleAlg: Literal["near", "bilinear", "cubic", "average"] = "near",
    _warpKwargs={},
    _skipFiltering: bool = False,
):
    """Create a raster source surrounding the Extent from a collection of other rasters.

    Parameters
    ----------
    sources : list, or something acceptable to gk.Extent.filterSources
        The sources to add together over the invoking Extent

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    if _skipFiltering:
        sources = sorted(list(sources))
    else:
        sources = sorted(list(self.filterSources(sources)))

    if len(sources) == 0:
        warnings.warn("No suitable sources found")
        return None

    raster_info = RASTER.rasterInfo(sources[0])

    ext = self.castTo(raster_info.srs).fit((raster_info.dx, raster_info.dy))

    master_raster = ext._quickRaster(
        dx=raster_info.pixelWidth,
        dy=raster_info.pixelHeight,
        noData=raster_info.noData,
        scale=raster_info.scale,
        offset=raster_info.offset,
        dtype=raster_info.data_type_name_str,
    )
    gdal.Warp(
        master_raster,
        sources,
        resampleAlg=resampleAlg,
        **_warpKwargs,
    )

    return master_raster

rasterize

rasterize(
    source, pixelWidth, pixelHeight, strict=True, **kwargs
)

Convenience function for geokit.vector.rasterize() which automatically sets the 'srs' and 'bounds' input.

Note:

When creating an 'in memory' raster vs one which is saved to disk, a slightly different algorithm is used which can sometimes add an extra row of pixels. Be aware of this if you intend to compare value-matricies directly from rasters generated with this function.

Parameters:

  • source

    (str) –

    The path to the vector file to load

  • pixelHeight

    (numeric; optional) –

    The pixel height (y-resolution) of the output raster * Only required if this value should be changed

  • pixelWidth

    (numeric; optional) –

    The pixel width (x-resolution) of the output raster * Only required if this value should be changed

  • strict

    (bool, default: True ) –

    If True, raise an error if trying to rasterize to a pixelWidth and pixelHeight which does not fit into the Extent

  • **kwargs

    All other keyword arguments are passed on to geokit.raster.warp()

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def rasterize(self, source, pixelWidth, pixelHeight, strict=True, **kwargs):
    """Convenience function for geokit.vector.rasterize() which automatically
    sets the 'srs' and 'bounds' input.

    Note:
    -----
    When creating an 'in memory' raster vs one which is saved to disk, a slightly
    different algorithm is used which can sometimes add an extra row of pixels. Be
    aware of this if you intend to compare value-matricies directly from rasters
    generated with this function.

    Parameters
    ----------
    source : str
        The path to the vector file to load

    pixelHeight : numeric; optional
        The pixel height (y-resolution) of the output raster
        * Only required if this value should be changed

    pixelWidth : numeric; optional
        The pixel width (x-resolution) of the output raster
        * Only required if this value should be changed

    strict : bool
        If True, raise an error if trying to rasterize to a pixelWidth and
        pixelHeight which does not fit into the Extent

    **kwargs:
        All other keyword arguments are passed on to geokit.raster.warp()

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    if strict and not self.fitsResolution((pixelWidth, pixelHeight)):
        raise GeoKitExtentError("The given resolution does not fit to the Extent boundaries")
    return VECTOR.rasterize(
        source=source,
        pixelWidth=pixelWidth,
        pixelHeight=pixelHeight,
        srs=self.srs,
        bounds=self.xyXY,
        **kwargs,
    )

shift

shift(dx=0, dy=0) -> Extent

Shift the extent in the X and/or Y dimensions.

Parameters:

  • dx

    (float, default: 0 ) –

    The amount to shift in the x dimension * In units of the extent's srs

  • dy

    (float, default: 0 ) –

    The amount to shift in the y dimension * In units of the extent's srs

Returns:

Source code in geokit/core/extent.py
def shift(self, dx=0, dy=0) -> "Extent":
    """Shift the extent in the X and/or Y dimensions.

    Parameters
    ----------
    dx : float
        The amount to shift in the x dimension
        * In units of the extent's srs

    dy : float
        The amount to shift in the y dimension
        * In units of the extent's srs

    Returns
    -------
    Extent
    """
    return Extent(self.xMin + dx, self.yMin + dy, self.xMax + dx, self.yMax + dy, srs=self.srs)

subTiles

subTiles(zoom, asGeom=False)

Generates tile Extents at a given zoom level which encompass the invoking Extent.

Parameters:

  • zoom

    (int) –

    The zoom level of the expected tile source

  • asGeom

    (bool, default: False ) –

    If True, returns tuple of ogr.Geometries in stead of (xi,yi,zoom) tuples

Returns:

  • Generator of Geometries or (xi,yi,zoom) tuples
Source code in geokit/core/extent.py
def subTiles(self, zoom, asGeom=False):
    """Generates tile Extents at a given zoom level which encompass the invoking Extent.

    Parameters
    ----------
    zoom : int
        The zoom level of the expected tile source

    asGeom : bool
        If True, returns tuple of ogr.Geometries in stead of (xi,yi,zoom) tuples

    Returns
    -------
    Generator of Geometries or (xi,yi,zoom) tuples
    """
    yield from GEOM.subTiles(self.box, zoom, checkIntersect=False, asGeom=asGeom)

tileBox

tileBox(zoom: int, return_index_box: bool = False)

Determine the tile Extent at a given zoom level which surround the invoked Extent.

Parameters:

  • zoom

    (int) –

    The zoom level of the expected tile source

  • return_index_box

    (bool, default: False ) –

    If true, also return the index box at the specified zoom level (from self.tileIndexBox)

Returns:

  • if return_index_box is False: geokit.Extent
  • if return_index_box is True: Tuple
    • Item 0: geokit.Extent
    • Item 1: namedtuple(xi_start, xi_stop, yi_start, yi_stop)
Source code in geokit/core/extent.py
def tileBox(self, zoom: int, return_index_box: bool = False):
    """Determine the tile Extent at a given zoom level which surround the invoked Extent.

    Parameters
    ----------
    zoom : int
        The zoom level of the expected tile source

    return_index_box : bool
        If true, also return the index box at the specified zoom level (from self.tileIndexBox)

    Returns
    -------
    if return_index_box is False: geokit.Extent

    if return_index_box is True: Tuple
        - Item 0: geokit.Extent
        - Item 1: namedtuple(xi_start, xi_stop, yi_start, yi_stop)
    """
    # Get Bounds of new raster in EPSG3857
    tb = self.tileIndexBox(zoom)

    tl_tile_xi = tb.xi_start
    tl_tile_yi = tb.yi_start
    br_tile_xi = tb.xi_stop
    br_tile_yi = tb.yi_stop

    tl_lat, tl_lon = smopy.num2deg(tl_tile_xi, tl_tile_yi, zoom)
    br_lat, br_lon = smopy.num2deg(br_tile_xi + 1, br_tile_yi + 1, zoom)

    coords3857 = SRS.xyTransform(
        [(tl_lon, tl_lat), (br_lon, br_lat)],
        fromSRS=SRS.EPSG4326,
        toSRS=SRS.EPSG3857,
        outputFormat="xy",
    )

    ext = Extent(
        coords3857.x.min(),
        coords3857.y.min(),
        coords3857.x.max(),
        coords3857.y.max(),
        srs=SRS.EPSG3857,
    )

    if return_index_box:
        return ext, tb
    else:
        return ext

tileIndexBox

tileIndexBox(zoom: int)

Determine the tile indexes at a given zoom level which surround the invoked Extent.

Parameters:

  • zoom

    (int) –

    The zoom level of the expected tile source

Returns:

  • namedtuple
    • xi_start: int - The starting x index
    • xi_stop: int - The ending x index
    • yi_start: int - The starting y index
    • yi_stop: int - The ending y index
Source code in geokit/core/extent.py
def tileIndexBox(self, zoom: int):
    """Determine the tile indexes at a given zoom level which surround the invoked Extent.

    Parameters
    ----------
    zoom : int
        The zoom level of the expected tile source

    Returns
    -------
    namedtuple:
        - xi_start: int - The starting x index
        - xi_stop:  int - The ending x index
        - yi_start: int - The starting y index
        - yi_stop:  int - The ending y index
    """
    ext4326 = self.castTo(SRS.EPSG4326)

    tl_tile_xi, tl_tile_yi = smopy.deg2num(ext4326.yMax, ext4326.xMin, zoom)
    br_tile_xi, br_tile_yi = smopy.deg2num(ext4326.yMin, ext4326.xMax, zoom)

    return TileIndexBox(
        xi_start=tl_tile_xi,
        xi_stop=br_tile_xi,
        yi_start=tl_tile_yi,
        yi_stop=br_tile_yi,
        zoom=zoom,
    )

tileMosaic

tileMosaic(source: str, zoom: int, **kwargs)

Create a raster source surrounding the Extent from a collection of tiles.

Parameters:

  • source

    (str) –

    The source to fetch tiles from * Must include indicators for: {z} -> The tile's zoom level {x} -> The tile's x-index {y} -> The tile's y-index * Ex: File on disk : "/path/to/tile/directory/{z}/{x}/{y}/filename.tif" Remote HTTP file : "/vsicurl_streaming/http://path/to/resource/{z}/{x}/{y}/filename.tif" * Find more info at https://gdal.org/user/virtual_file_systems.html

  • zoom

    (int) –

    The zoom level of the expected tile source

  • pixelsPerTile

    ((int, (int, int))) –

    The number of pixels found in each tile

  • workingType

    (dtype) –

    The datatype of the working matrix (should match the raster source)

  • noData

    (numeric) –

    The value to treat as 'no data'

  • output

    (str) –

    An optional path for an output raster (.tif) file

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def tileMosaic(self, source: str, zoom: int, **kwargs):
    """Create a raster source surrounding the Extent from a collection of tiles.

    Parameters
    ----------
    source : str
        The source to fetch tiles from
        * Must include indicators for:
          {z} -> The tile's zoom level
          {x} -> The tile's x-index
          {y} -> The tile's y-index
        * Ex:
          File on disk     : "/path/to/tile/directory/{z}/{x}/{y}/filename.tif"
          Remote HTTP file : "/vsicurl_streaming/http://path/to/resource/{z}/{x}/{y}/filename.tif"
        * Find more info at https://gdal.org/user/virtual_file_systems.html

    zoom : int
        The zoom level of the expected tile source

    pixelsPerTile : int, (int,int)
        The number of pixels found in each tile

    workingType : np.dtype
        The datatype of the working matrix (should match the raster source)

    noData : numeric
        The value to treat as 'no data'

    output : str
        An optional path for an output raster (.tif) file

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    sources = list(self.tileSources(zoom=zoom, source=source))
    return self.rasterMosaic(sources, _skipFiltering=True, **kwargs)

tileSources

tileSources(zoom: int, source: str | None = None)

Get the tiles sources which contribute to the invoking Extent.

Parameters:

  • zoom

    (int) –

    The zoom level of the expected tile source

  • source

    (str, default: None ) –

    The source to fetch tiles from * Must include indicators for: {z} -> The tile's zoom level {x} -> The tile's x-index {y} -> The tile's y-index * Ex: File on disk : "/path/to/tile/directory/{z}/{x}/{y}/filename.tif" Remote HTTP file : "/vsicurl_streaming/http://path/to/resource/{z}/{x}/{y}/filename.tif" * Find more info at https://gdal.org/user/virtual_file_systems.html

Yields:

  • if source is given: str
  • if source is not given: (xi,yi,zoom)
Source code in geokit/core/extent.py
def tileSources(self, zoom: int, source: str | None = None):
    """Get the tiles sources which contribute to the invoking Extent.

    Parameters
    ----------
    zoom : int
        The zoom level of the expected tile source

    source : str
        The source to fetch tiles from
        * Must include indicators for:
          {z} -> The tile's zoom level
          {x} -> The tile's x-index
          {y} -> The tile's y-index
        * Ex:
          File on disk     : "/path/to/tile/directory/{z}/{x}/{y}/filename.tif"
          Remote HTTP file : "/vsicurl_streaming/http://path/to/resource/{z}/{x}/{y}/filename.tif"
        * Find more info at https://gdal.org/user/virtual_file_systems.html

    Yields
    ------
    if source is given:     str
    if source is not given: (xi,yi,zoom)
    """
    tb = self.tileIndexBox(zoom=zoom)
    for xi in range(tb.xi_start, tb.xi_stop + 1):
        for yi in range(tb.yi_start, tb.yi_stop + 1):
            if source is None:
                yield (xi, yi, zoom)
            else:
                yield (source.replace("{z}", str(zoom)).replace("{x}", str(xi)).replace("{y}", str(yi)))

warp

warp(
    source: load_raster_input,
    pixelWidth,
    pixelHeight,
    strict=True,
    **kwargs,
)

Convenience function for geokit.raster.warp() which automatically sets the 'srs' and 'bounds' input.

Note:

When creating an 'in memory' raster vs one which is saved to disk, a slightly different algorithm is used which can sometimes add an extra row of pixels. Be aware of this if you intend to compare value-matricies directly from rasters generated with this function.

Parameters:

  • source

    (str) –

    The path to the vector file to load

  • pixelHeight

    (numeric; optional) –

    The pixel height (y-resolution) of the output raster * Only required if this value should be changed

  • pixelWidth

    (numeric; optional) –

    The pixel width (x-resolution) of the output raster * Only required if this value should be changed

  • strict

    (bool, default: True ) –

    If True, raise an error if trying to warp to a pixelWidth and pixelHeight which does not fit into the Extent

  • **kwargs

    All other keyword arguments are passed on to geokit.raster.warp()

Returns:

  • * If 'output' is None: gdal.Dataset
  • * If 'output' is a string: None
Source code in geokit/core/extent.py
def warp(self, source: load_raster_input, pixelWidth, pixelHeight, strict=True, **kwargs):
    """Convenience function for geokit.raster.warp() which automatically sets the
    'srs' and 'bounds' input.

    Note:
    -----
    When creating an 'in memory' raster vs one which is saved to disk, a slightly
    different algorithm is used which can sometimes add an extra row of pixels. Be
    aware of this if you intend to compare value-matricies directly from rasters
    generated with this function.

    Parameters
    ----------
    source : str
        The path to the vector file to load

    pixelHeight : numeric; optional
        The pixel height (y-resolution) of the output raster
        * Only required if this value should be changed

    pixelWidth : numeric; optional
        The pixel width (x-resolution) of the output raster
        * Only required if this value should be changed

    strict : bool
        If True, raise an error if trying to warp to a pixelWidth and
        pixelHeight which does not fit into the Extent

    **kwargs:
        All other keyword arguments are passed on to geokit.raster.warp()

    Returns
    -------
    * If 'output' is None: gdal.Dataset
    * If 'output' is a string: None
    """
    if strict and not self.fitsResolution((pixelWidth, pixelHeight)):
        raise GeoKitExtentError("The given resolution does not fit to the Extent boundaries")
    return RASTER.warp(
        source=source,
        pixelWidth=pixelWidth,
        pixelHeight=pixelHeight,
        srs=self.srs,
        bounds=self.xyXY,
        **kwargs,
    )