コード例 #1
0
ファイル: pyramids.py プロジェクト: pombredanne/gislib
    def sync(self):
        """
        Update a peak pyramid.

        Pyramids with large tilesizes warp slow at high zoomlevels. The
        use of a peak pyramid with a small tilesize on top of the main
        pyramid solves that.
        """
        path = os.path.join(self.path, self.PEAK)
        info = self.actualinfo
        if os.path.exists(path):
            shutil.rmtree(path)
        peak = Pyramid(path)
        dataset = self.get_dataset(info['top_tile'])

        # Base of peak is one higher than tile
        base = MEM.Create('',
                          info['tilesize'][0] // 2,
                          info['tilesize'][1] // 2,
                          1,
                          info['datatype'])
        base.SetProjection(info['projection'])
        base.GetRasterBand(1).SetNoDataValue(info['nodatavalue'])
        base.SetGeoTransform(
            scale_geotransform(dataset.GetGeoTransform(), 2),
        )
        base.GetRasterBand(1).Fill(info['nodatavalue'])
        rasters.reproject(dataset, base)
        peak.add(base, sync=False, blocksize=(256, 256), tilesize=(256, 256))
コード例 #2
0
ファイル: pyramids.py プロジェクト: pombredanne/gislib
    def warpinto(self, dataset):
        """ Warp data from the pyramid into dataset. """
        # if no pyramid info, pyramid is empty.
        info = self.info
        if info is None:
            return

        # get bounds in pyramids projection
        bounds = get_bounds(dataset=dataset, projection=info['projection'])
        level = max(info['min_level'], get_level(bounds['pixel']))

        # warp from peak if appropriate
        if level > info['max_level'] and 'peak' in info:
            return info['peak'].warpinto(dataset)

        # This is the top of the main pyramid (level == max_level) or the peak
        if level >= info['max_level']:
            tiles = info['top_tile'],
        else:
            tiles = get_tiles(
                tilesize=info['tilesize'],
                level=level,
                extent=vectors.Geometry(bounds['raster']).extent,
            )
        for source in self.get_datasets(tiles):
            rasters.reproject(source, dataset)
コード例 #3
0
ファイル: pyramids.py プロジェクト: SiggyF/gislib
    def sync(self):
        """
        Create or replace the peak with current data.
        """
        ### XXX
        # Only create an empty file with name of peakpath
        open(self.peakpath, 'w')
        return

        cropped = []
        for dataset in self.get_datasets(-1):
            cropped.append(crop(dataset))
        extents = [dataset2outline(c).extent for c in cropped]
        x1, y1, x2, y2 = zip(*extents)
        x1, y1, x2, y2 = min(x1), min(y1), max(x2), max(y2)
        geotransform = x1, (x2 - x1) / 256, 0, y2, 0, (y1 - y2) / 256

        # create
        fd, temppath = tempfile.mkstemp(dir=self.path, prefix=b'.pyramid.tmp.')
        dataset = GDAL_DRIVER_GTIFF.Create(temppath,
                                           256,
                                           256,
                                           self.raster_count,
                                           self.data_type,
                                           get_options(block_size=(256, 256)))
        dataset.SetProjection(projections.get_wkt(self.projection))
        dataset.SetGeoTransform(geotransform)
        for i in range(self.raster_count):
            dataset.GetRasterBand(i + 1).SetNoDataValue(self.no_data_value)
        for c in cropped:
            rasters.reproject(c, dataset)

        dataset = None
        os.close(fd)
        os.rename(temppath, self.peakpath)
コード例 #4
0
ファイル: pyramids.py プロジェクト: SiggyF/gislib
def warp(path_and_blocks):
    """ Warp global transport into specified blocks from dataset at path. """
    path, blocks = path_and_blocks
    for i, j in blocks:
        dataset = rasters.Dataset(gdal.Open(path, gdal.GA_Update))
        block = dataset.read_block((i, -j - 1))
        rasters.reproject(source=transport.dataset, target=block['dataset'])
        block['dataset'].FlushCache()  # really update underlying numpy array
        dataset.write_block((i, -j - 1), block['array'])
コード例 #5
0
ファイル: pyramids.py プロジェクト: pombredanne/gislib
    def get_promoted(self, tile, info):
        """
        Return parent tile.

        Reproject tiles dataset into parent dataset.
        """
        parent = get_parent(tile)
        source = self.get_dataset(tile)
        target = self.get_dataset(tile=parent, info=info)
        rasters.reproject(source, target)
        return parent
コード例 #6
0
ファイル: pyramids.py プロジェクト: pombredanne/gislib
    def add(self, dataset=None, sync=True, **kwargs):
        """
        If there is no dataset, check if locked and reload.

        Any kwargs are used to override dataset projection and datatype,
        nodatavalue, tilesize. Kwargs are ignored if data already exists
        in the pyramid.

        Sync indicates wether to build a synced peak on top of the pyramid.
        """
        self.lock()

        if dataset is None:
            # unlock and return
            return self.unlock()

        # use pyramid info if possible, otherwise use dataset and kwargs
        info = self.actualinfo
        if info is None:
            info = get_info(dataset)
            info.update(kwargs)
            if not self.path.endswith(self.PEAK):
                info.update(peak=Pyramid(os.path.join(self.path, self.PEAK)))

        # get bounds in pyramids projection
        bounds = get_bounds(dataset=dataset, projection=info['projection'])

        # derive baselevel
        min_level = info.get('min_level', get_level(bounds['pixel']))

        # find new top tile
        top_tile = get_top_tile(geometry=bounds['raster'],
                                tilesize=info['tilesize'],
                                blocksize=info['blocksize'])

        # walk and reproject
        tiles = walk_tiles(tile=top_tile,
                           stop=min_level,
                           geometry=bounds['raster'])

        children = collections.defaultdict(list)
        previous_level = min_level
        for tile in tiles:
            # Get the dataset
            target = self.get_dataset(tile=tile, info=info)

            # To aggregate or not
            if tile.level == previous_level + 1:
                while children[previous_level]:
                    rasters.reproject(
                        children[previous_level].pop(), target
                    )
            else:
                rasters.reproject(dataset, target)
            target = None  # Writes the header

            children[tile.level].append(self.get_dataset(tile))
            previous_level = tile.level

        # sync old and new toptiles
        lo, hi = top_tile, info.get('top_tile', top_tile)
        if hi.level < lo.level:
            hi, lo = lo, hi  # swap
        while lo.level < hi.level:
            lo = self.get_promoted(tile=lo, info=info)
        while lo.indices != hi.indices:
            lo = self.get_promoted(tile=lo, info=info)
            hi = self.get_promoted(tile=hi, info=info)

        # Update peak
        if sync:
            self.sync()

        self.unlock()
コード例 #7
0
ファイル: pyramids.py プロジェクト: SiggyF/gislib
 def warpinto(self, dataset):
     """ Warp appropriate tiles into dataset. """
     for source in self.get_datasets(dataset):
         rasters.reproject(source, dataset)