def affine_transformation(anchor_x, x0, x1, anchor_y, y0, y1):
    """Construct an affine coordinate transform and its inverse.

    From a GDAL-style specification of the parameters of an affine
    transformation, construct both the affine function that maps integer cell
    indices to the center points of the corresponding cells, and points in a
    cell to the cell they belong to. The point (anchor_x, anchor_y) is a corner
    of the cell (0, 0).

    Parameters
    ==========
    anchor_x: X-Coordinate of a corner of the cell (0, 0)
    x0: Increase in X-Coordinate between cells (0, 0) and (1, 0)
    x1: Increase in X-Coordinate between cells (0, 0) and (0, 1)
    anchor_y: Y-Coordinate of a corner of the cell (0, 0)
    y0: Increase in Y-Coordinate between cells (0, 0) and (1, 0)
    y1: Increase in Y-Coordinate between cells (0, 0) and (0, 1)

    Returns
    =======
    coordinates_for_cell: Function mapping integer indices to coordinates
    cell_for_coordinates: Function mapping coordinates to the cell they lie indices

    Examples
    ========

    >>> integer_grid_mids, integer_grid_cell = affine_transformation(0, 1, 0, 0, 0, 1)
    >>> integer_grid_mids(0, 0)
    (0.5, 0.5)
    >>> integer_grid_cell((9.4, 2.1))
    (9, 2)

    >>> shifted_grid_mids, shifted_grid_cell = affine_transformation(5, 1, 0, 2, 0, 1)
    >>> shifted_grid_mids(0, 0)
    (5.5, 2.5)
    >>> shifted_grid_cell((9.4, 2.1))
    (4, 0)

    >>> forward, back = affine_transformation(*numpy.random.normal(size=6))
    >>> back(forward(0, 0))
    (0, 0)
    >>> back(forward(3, 4))
    (3, 4)
    """
    def coordinates_for_cell(col, row):
        col += 0.5
        row += 0.5
        return (anchor_x + x0 * col + x1 * row,
                anchor_y + y0 * col + y1 * row)
    def cell_for_coordinates(coordinates):
        coeff = 1 / (x0 * y1 - x1 * y0)
        x_raw, y_raw = coordinates
        x = x_raw - anchor_x
        y = y_raw - anchor_y
        col = coeff * (y1 * x - x1 * y)
        row = coeff * (-y0 * x + x0 * y)
        # int() truncates towards 0, so we have to use something else.
        # Negative cell indices *should* not appear, but who knows what else this function will be used for!
        return (int(col), int(row))
    return coordinates_for_cell, cell_for_coordinates