Tile

Source code in geocube/entities/tile.py
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@dataclass
class Tile:
    crs:       str
    transform: affine.Affine  # Pixel to crs
    shape:     Tuple[int, int]

    @classmethod
    def from_pb(cls, pb: layouts_pb2.Tile):
        return cls(pb.crs, affine.Affine(pb.transform.b, pb.transform.c, pb.transform.a,
                                         pb.transform.e, pb.transform.f, pb.transform.d),
                   shape=(int(pb.size_px.width), int(pb.size_px.height))
                   )

    @classmethod
    def from_geotransform(cls, transform: Union[affine.Affine, Tuple[float, float, float, float, float, float]],
                          crs: Union[str, int], shape: Tuple[int, int]) -> Tile:
        """
        Create a tile from a geotransform, a crs and a shape
        Args:
            transform: geotransform from pixel coordinates to CRS.
            crs: Coordinate Reference System of the tile
            shape: shape of the tile (in pixel) (@warning shape is the transpose of numpy shape)

        Returns:
            A new tile
        """
        return cls(crs_to_str(crs), Tile._parse_geotransform(transform), shape)

    @classmethod
    def from_record(cls, record: entities.Record, crs: Union[str, int], resolution: float) -> Tile:
        """ Create a tile that cover the record in the crs at a given resolution
        Warning: record.aoi must be loaded (with client.load_aoi())
        Warning: Check the `result.shape` as the size might be huge !
        Warning: the aoi is converted to the crs, but it might be imprecise at the borders

        Args:
            record:
            crs: Coordinate Reference System of the tile
            resolution: resolution of the pixel in the CRS

        Returns:
            A new tile
        """
        return Tile.from_aoi(record.aoi, crs, resolution)

    @classmethod
    def from_bbox(cls, bbox: Tuple[float, float, float, float], crs: Union[str, int],
                  resolution: Union[float, Tuple[float, float]]) -> Tile:
        """
        Create a tile from a bbox, a crs and a resolution
        Args:
            bbox : (x1, y1, x2, y2) in crs coordinates
            crs : (Coordinate Reference System) of the tile
            resolution : of the pixel in the CRS

        Returns:
            A new tile
        """
        rx, ry = resolution if isinstance(resolution, tuple) else (resolution, -resolution)
        x1, y1, x2, y2 = bbox
        if math.copysign(1, rx)*(x2-x1) < 0:
            x1, x2 = x2, x1
        if math.copysign(1, ry)*(y2-y1) < 0:
            y1, y2 = y2, y1
        transform = geo_transform(x1, y1, resolution)
        sx, sy = (~transform) * (x2, y2)
        return cls(crs_to_str(crs), transform, (math.ceil(sx), math.ceil(sy)))

    @classmethod
    def from_aoi(cls, aoi: geometry.MultiPolygon, crs: Union[str, int],
                 resolution: Union[float, Tuple[float, float]]) -> Tile:
        """

        Args:
            aoi : multipolygon in 4326 coordinates
            crs : (Coordinate Reference System) of the tile
            resolution : of the pixel in the CRS

        Returns:
            A new tile
        """
        return Tile.from_bbox(gpd.GeoSeries(aoi, crs=4326).to_crs(crs).total_bounds, crs=crs, resolution=resolution)

    def __str__(self):
        return "Tile {}\n" \
               "    transform: ({}, {} {}, {}, {} {})\n" \
               "    bounds:    {} {}\n" \
               "    shape:     {} \n" \
               "    crs:       {}\n".format(self.shape,
                                            self.transform.c, self.transform.a, self.transform.b,
                                            self.transform.f, self.transform.d, self.transform.e,
                                            self.transform*(0, 0), self.transform*self.shape,
                                            self.shape, self.crs)

    def __repr__(self):
        return self.__str__()

    def geoseries(self) -> gpd.GeoSeries:
        x1, y1 = self.transform*(0, 0)
        x2, y2 = self.transform*self.shape
        p = geometry.Polygon([[x1, y1], [x1, y2], [x2, y2], [x2, y1], [x1, y1]])
        return gpd.GeoSeries(p, crs=self.crs)

    def geometry(self, to_crs: Union[str, int] = None):
        gs = self.geoseries()
        if to_crs is not None:
            gs = gs.to_crs(crs_to_str(to_crs))
        return gs.iloc[0]

    def reshape(self, i1, j1, i2, j2) -> entities.Tile:
        """ Create a new Tile using the coordinate pixels
         @warning inverse of numpy coordinates """
        return Tile.from_bbox(self.transform*(i1, j1) + self.transform*(i2, j2),
                              self.crs, resolution=(self.transform.a, self.transform.e))

    @staticmethod
    def _parse_geotransform(transform: Union[affine.Affine, Tuple[float, float, float, float, float, float]]) \
            -> affine.Affine:
        if isinstance(transform, affine.Affine):
            return transform
        return affine.Affine.from_gdal(*transform)

    @staticmethod
    def to_geoseries(tiles: List[Tile]):
        """ return list of Tiles as geoseries """
        return gpd.GeoSeries(pd.concat([t.geoseries().to_crs("epsg:4326") for t in tiles]))

    @staticmethod
    def plot(tiles: List[Tile], **kwargs):
        """ kwargs: additional arguments for utils.plot_aoi """
        return utils.plot_aoi(Tile.to_geoseries(tiles), **kwargs)

from_aoi(aoi, crs, resolution) classmethod

Parameters:
  • aoi

    multipolygon in 4326 coordinates

  • crs

    (Coordinate Reference System) of the tile

  • resolution

    of the pixel in the CRS

Returns:
  • Tile

    A new tile

Source code in geocube/entities/tile.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@classmethod
def from_aoi(cls, aoi: geometry.MultiPolygon, crs: Union[str, int],
             resolution: Union[float, Tuple[float, float]]) -> Tile:
    """

    Args:
        aoi : multipolygon in 4326 coordinates
        crs : (Coordinate Reference System) of the tile
        resolution : of the pixel in the CRS

    Returns:
        A new tile
    """
    return Tile.from_bbox(gpd.GeoSeries(aoi, crs=4326).to_crs(crs).total_bounds, crs=crs, resolution=resolution)

from_bbox(bbox, crs, resolution) classmethod

Create a tile from a bbox, a crs and a resolution Args: bbox : (x1, y1, x2, y2) in crs coordinates crs : (Coordinate Reference System) of the tile resolution : of the pixel in the CRS

Returns:
  • Tile

    A new tile

Source code in geocube/entities/tile.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
@classmethod
def from_bbox(cls, bbox: Tuple[float, float, float, float], crs: Union[str, int],
              resolution: Union[float, Tuple[float, float]]) -> Tile:
    """
    Create a tile from a bbox, a crs and a resolution
    Args:
        bbox : (x1, y1, x2, y2) in crs coordinates
        crs : (Coordinate Reference System) of the tile
        resolution : of the pixel in the CRS

    Returns:
        A new tile
    """
    rx, ry = resolution if isinstance(resolution, tuple) else (resolution, -resolution)
    x1, y1, x2, y2 = bbox
    if math.copysign(1, rx)*(x2-x1) < 0:
        x1, x2 = x2, x1
    if math.copysign(1, ry)*(y2-y1) < 0:
        y1, y2 = y2, y1
    transform = geo_transform(x1, y1, resolution)
    sx, sy = (~transform) * (x2, y2)
    return cls(crs_to_str(crs), transform, (math.ceil(sx), math.ceil(sy)))

from_geotransform(transform, crs, shape) classmethod

Create a tile from a geotransform, a crs and a shape Args: transform: geotransform from pixel coordinates to CRS. crs: Coordinate Reference System of the tile shape: shape of the tile (in pixel) (@warning shape is the transpose of numpy shape)

Returns:
  • Tile

    A new tile

Source code in geocube/entities/tile.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@classmethod
def from_geotransform(cls, transform: Union[affine.Affine, Tuple[float, float, float, float, float, float]],
                      crs: Union[str, int], shape: Tuple[int, int]) -> Tile:
    """
    Create a tile from a geotransform, a crs and a shape
    Args:
        transform: geotransform from pixel coordinates to CRS.
        crs: Coordinate Reference System of the tile
        shape: shape of the tile (in pixel) (@warning shape is the transpose of numpy shape)

    Returns:
        A new tile
    """
    return cls(crs_to_str(crs), Tile._parse_geotransform(transform), shape)

from_record(record, crs, resolution) classmethod

Create a tile that cover the record in the crs at a given resolution Warning: record.aoi must be loaded (with client.load_aoi()) Warning: Check the result.shape as the size might be huge ! Warning: the aoi is converted to the crs, but it might be imprecise at the borders

Parameters:
  • record (Record) –
  • crs (Union[str, int]) –

    Coordinate Reference System of the tile

  • resolution (float) –

    resolution of the pixel in the CRS

Returns:
  • Tile

    A new tile

Source code in geocube/entities/tile.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@classmethod
def from_record(cls, record: entities.Record, crs: Union[str, int], resolution: float) -> Tile:
    """ Create a tile that cover the record in the crs at a given resolution
    Warning: record.aoi must be loaded (with client.load_aoi())
    Warning: Check the `result.shape` as the size might be huge !
    Warning: the aoi is converted to the crs, but it might be imprecise at the borders

    Args:
        record:
        crs: Coordinate Reference System of the tile
        resolution: resolution of the pixel in the CRS

    Returns:
        A new tile
    """
    return Tile.from_aoi(record.aoi, crs, resolution)

plot(tiles, **kwargs) staticmethod

kwargs: additional arguments for utils.plot_aoi

Source code in geocube/entities/tile.py
164
165
166
167
@staticmethod
def plot(tiles: List[Tile], **kwargs):
    """ kwargs: additional arguments for utils.plot_aoi """
    return utils.plot_aoi(Tile.to_geoseries(tiles), **kwargs)

reshape(i1, j1, i2, j2)

Create a new Tile using the coordinate pixels @warning inverse of numpy coordinates

Source code in geocube/entities/tile.py
146
147
148
149
150
def reshape(self, i1, j1, i2, j2) -> entities.Tile:
    """ Create a new Tile using the coordinate pixels
     @warning inverse of numpy coordinates """
    return Tile.from_bbox(self.transform*(i1, j1) + self.transform*(i2, j2),
                          self.crs, resolution=(self.transform.a, self.transform.e))

to_geoseries(tiles) staticmethod

return list of Tiles as geoseries

Source code in geocube/entities/tile.py
159
160
161
162
@staticmethod
def to_geoseries(tiles: List[Tile]):
    """ return list of Tiles as geoseries """
    return gpd.GeoSeries(pd.concat([t.geoseries().to_crs("epsg:4326") for t in tiles]))