Releases: locationtech/geotrellis
v2.1.0
gerotrellis.sparkgeotrellis.spark.testkitTestEnvironmentnow includesSparkSession(#2808).
geotrellis.spark.etl- Add
TemporalIngestmain method (#2709).
- Add
geotrellis.rasterRasterRegionReprojectdefaults to approximate resampling forMultibandBandTile(#2803).Stitchertype class instance is now defined forTileFeature[T, D]([#2803 (https://github.com//pull/2803)).- Fix
GeoTiffSegmentconversion toUByteCellTypeandUShortCellType(#2794). - Fix
GeoTiff[T]interpretation ofAutoHigherResolutionOverviewStrategy(#2802). GeoTiff[T].getClosestOverviewmethod is now public (#2804).GeoTiffOptions.storageMethodnow defaults toTiledinstead ofStriped(#2810).- GeoTiff
TiffTagsclass can now read inverted extents (#2812).
geotrellis.vector- Add
bboxfield to all GeoJSON Features (#2811).
- Add
v2.0.0
Additions
-
geotrellis.spark- All focal operations now except an optional
partitionerparameter. BufferTiles.applymethods and thebufferTilesmethods now except an optionalpartitionerparameter.CollectionLayerReadernow has an SPI interface.ZoomResamplecan now be used onMultibandTileLayerRDD.Partitionercan be specified in thereprojectmethods ofTileLayerRDD.- Compression
levelof GeoTiffs can be specified in theDeflateCompressionconstructor. resampleMethodparameter has been added toCOGLayerWriter.Options.- A new type called
LayerTypehas been created to help identify the nature of a layer (either Avro or COG). LayerHeadernow have an additional parameter:layerType.AttributeStorenow has four new methods:layerType,isCOGLayer,readCOGLayerAttributes, andwriteCOGLayerAttributes.- Kryo serialization of geometry now uses a binary format to reduce shuffle block size.
- Alter
geotrellis.spark.stitch.StitchRDDMethodsto allowRDD[(K, V)]to be stitched when not all tiles are of the same dimension. - Introduce
Pyramidclass to provide a convenience wrapper for building raster pyramids. COGValueReaderandOverzoomingCOGValueReaderhave thereadSubsetBandsmethod which allows reading bands subsets.COGLayerReadernow has thereadSubsetBandsandquerySubsetBandsmethods which allow users to read in layers with the desired bands in the order they choose.KeyBoundsnow has therekeymethod that will rekey the bounds from a source layout to a target layout.
- All focal operations now except an optional
-
geotrellis.raster- Kryo serialization of geometry now uses a binary format to reduce shuffle block size.
GeoTiffMultibandTilenow has anothercropmethod that takes aGridBoundsand anArray[Int]that represents the band indices.GeoTiff[MultibandTile]can be written withBandInterleave, onlyPixelInterleavepreviously supported. (#2767)MultibandTilenow has a new method,cropBandsthat takes an Array of band indices and returns a croppedMultibandTilewith the chosen bands.
-
geotrellis.spark-etlInput.partitionBytesand it is set to134217728by default to correspondHadoopGeoTiffRDD default behaviour.Output.bufferSizeoption to set up a custom buffer size for the buffered reprojection.
Changes
-
geotrellis.spark- The length of the key (the space-filling curve index or address) used for layer reading and writing has been extended from a fixed length of 8 bytes to an arbitrary length. This change affects not only the
geotrellis.sparkpackage, but all backends (excludinggeotrellis.geowaveandgeotrellis.geomesa). - Reprojection has improved performance due to one less shuffle stage and lower memory usage.
TileRDDReprojectloses dependency onTileReprojectMethodsin favor ofRasterRegionReproject - The Ascii draw methods are now method extensions of
Tile. - Replace
geotrellis.util.Functorwithcats.Functor. - Specifying the
maxTileSizefor a COGLayer that's to be written is now done viaCOGLayerWriter.Options
which can be passed directly to thewritemethods. - Specifying the
compressionfor a COGLayer that's to be written is now done viaCOGLayerWriter.Options
which can be passed directly to thewritemethods. - The attribute name for
COGLayerStorageMetadatais nowmetadatainstead ofcog_metadata. - Scalaz streams were replaced by fs2 streams.
- Refactored
HBaseInstance, now accepts a plain HadoopConfigurationobject. - Refactored
CassandraInstance, now accepts agetClusterfunction. - Use pureconfig to handle all work with configuration files.
- Removed
LayerUpdaterwith its functionality covered byLayerWriter(#2663).
of the same dimension. - Change
TilerMethods.tileToLayoutfunctions that acceptTileLayerMetadataas an argument to returnRDD[(K, V)] with Metadata[M]
instead ofRDD[(K, V)]. - Expose
attributeStoreparameter to LayerReader interface. - Added exponential backoffs in
S3RDDReader. - Changed SinglebandGeoTiff and MultibandGeoTiff crop function behaviour to work properly with cases when extent to crop by doesn't intersect tiff extent.
- All classes and objects in the
geowavepackage now use the spelling:GeoWavein their names. TileLayerMetadata.fromRddmethod has been renamed toTileLayerMetadata.fromRDD.KeyBounds.fromRddmethod has been renamed toKeyBounds.fromRDD.
- The length of the key (the space-filling curve index or address) used for layer reading and writing has been extended from a fixed length of 8 bytes to an arbitrary length. This change affects not only the
-
geotrellis.raster- Removed implicit conversion from
Raster[T]toT(#2771). - Removed
decompressoption fromGeoTiffReaderfunctions. - Scalaz streams were replaced by fs2 streams.
- Removed implicit conversion from
-
geotrellis.spark-etl- Package is deprecated since GeoTrellis 2.0.
Input.maxTileSizeis256by default to correspondHadoopGeoTiffRDD default behaviour.
-
geotrellis.slickgeotrellis.slick.Projectedhas been moved togeotrellis.vector.Projected
Fixes
- StreamingHistogram.binCount now returns non-zero counts (#2590)
- HilbertSpatialKeyIndex index offset. Existing spatial layers using Hilbert index will need to be updated (#2586)
- Fixed
CastExceptionthat sometimes occured when reading cached attributes. - Uncompressed
GeoTiffMultibandTileswill now convert to the correctCellType. - Calculating the Slope of a
TilewhentargetCellisDatawill now produce the correct result. - Introduce new hooks into
AttributeStoretrait to allow for better performance in certain queries against catalogs with many layers. GeoTiffReadercan now read tiffs that are missing theNewSubfileTypetag.- Pyramiding code will once again respect resampling method and will now actually reduce shuffle volume by resampling
tiles on map side of pyramid operation. COGLayerattributes can be accessed via the various read attribute methods in
AttributeStore(iereadMetadata,readHeader, etc)- The regex used to match files for the
HadoopLayerAttributeStoreandFileLayerAttributeStorehas been
expanded to include more characters. HadoopAttributeStore.availableAttributeshas been fixed so that it'll now list all attribute files.- Allow for simple features to be generated with a specified or random id with geometry stored in the standard
field, "the_geom" - Update version of Amazon SDK API to remove deprecation warnings.
- Fixed a bug in incorrect metadata fetch by
COGLayerReaderthat could lead to an incorrect data querying. - Cropping RDDs with
clamp=falsenow produces correct result. - Fixed tiff reads in case
RowsPerStriptiff tag is not defined. - Change aspect result to azimuth, i.e. start from due north and be clockwise.
- COG overviews generated in the
COGLayer.fromLayerRDDmethod will now use the passed inResampleMethod. - Reading a GeoTiff with
streamingwill now work with files that are larger thanjava.lang.Integer.MAX_VALUE. GeoTiffMultibandTile.cropwill now work with GeoTiffs that have tiled segments and band interleave.GeoTiffMultibandTile.cropwill now returnArrayMultibandTile(s) with the correct number of bands.- Improved performance of
COGValueReader.readSubsetBandswhen reading from S3.
1.2.1
1.2.0
API Changes
geotrellis.raster- Deprecation:
GridBounds.sizein favor ofGridBounds.sizeLong. - Deprecation:
GridBounds.coordsin favor ofGridBounds.coordsIter. - New:
GridBounds.offsetandGridBounds.bufferfor creating a modifiedGridBoundsfrom an existing one. - New:
ColorRamps.greyscale: Int => ColorRamp, which will generate a ramp when given some number of stops. - New:
ConstantTile.fromBytesto create any type ofConstantTilefrom anArray[Byte]. - New:
Tile.rotate90: Int => Tile,Tile.flipVertical: TileandTile.flipHorizontal: Tile.
- Deprecation:
geotrellis.vector- New:
Geometry.isEmpty: Boolean. This incurs much less overhead than previous ways of determining emptiness. - New:
Line.headandLine.lastfor efficiently grabbing the first or lastPointin theLine.
- New:
geotrellis.spark- Deprecation: The
LayerUpdatertrait hierarchy. UseLayerWriter.updateorLayerWriter.overwriteinstead. - Deprecation: Every cache provided by
geotrellis.spark.util.cache. These will be removed in favor of a pluggable cache in 2.0. - New:
SpatialKey.extent: LayoutDefinition => Extent - New:
ValueReader.attributeStore: AttributeStore - New:
TileLayerRDD.toSpatialReduce: ((V, V) => V) => TileLayerRDD[SpatialKey]for smarter folding of 3D tile layers into 2D tile layers. - The often-used
applymethod overloads inMapKeyTransformhave been given more descriptive aliases.
- Deprecation: The
geotrellis.vectortile(experimental)- New:
VectorTile.toGeoJsonandVectorTile.toIterable. - Library simplified by assuming the codec backend will always be Protobuf.
- New:
New Features
Rasterizing Geometry Layers
Finally, the full marriage of the vector, raster, and spark packages! You can now transform an RDD[Geometry] into a writable GeoTrellis layer of (SpatialKey, Tile)!
val geoms: RDD[Geometry] = ...
val celltype: CellType = ...
val layout: LayoutDefinition = ...
val value: Double = ... /* Value to fill the intersecting pixels with */
val layer: RDD[(SpatialKey, Tile)] with Metadata[LayoutDefinition] =
geoms.rasterize(value, celltype, layout)Clipping Geometry Layers to a Grid
In a similar vein to the above, you can now transform an arbitrarily
large collection of Geometries into a proper GeoTrellis layer, where the
sections of each Geometry are clipped to fit inside their enclosing
Extents.
Here we can see a large Line being clipped into nine sublines. It's
one method call:
import geotrellis.spark._
val layout: LayoutDefinition = ... /* The definition of your grid */
val geoms: RDD[Geometry] = ... /* Result of some previous work */
/* There are likely many clipped Geometries per SpatialKey... */
val layer: RDD[(SpatialKey, Geometry)] = geoms.clipToGrid(layout)
/* ... so we can group them! */
val grouped: RDD[(SpatialKey, Iterable[Geometry])] = layer.groupByKeyIf clipping on the Extent boundaries is not what you want, there are ways to customize this. See the ClipToGrid entry in our Scaladocs.
Sparkified Viewshed
A Viewshed shows "visibility" from some set vantage point, given an Elevation raster. Prior to GeoTrellis 1.2 this was possible at the individual Tile level but not the Layer (RDD) level. Now it is.
First, we need to think about the Viewpoint type:
import geotrellis.spark.viewshed._
val point: Viewpoint(
x = ..., // some coordinate.
y = ..., // some coordinate.
viewHeight = 4000, // 4 kilometres above the surface.
angle = Math.PI / 2, // direction that the "camera" faces (in radians). 0 == east.
fieldOfView = Math.PI / 2, // angular width of the "view port".
altitude = 0 // the height of points you're interested in seeing.
)In other words:
- x, y, viewHeight: where are we?
- angle: what direction are we looking?
- fieldOfView: how wide are we looking?
- altitude: how high/low is the "target" of our viewing?
Given a Seq[Viewpoint] (the algorithm supports multiple simultaneous
view points), we can do:
// Recall this common alias:
// type TileLayerRDD[K] = RDD[(K, Tile)] with Metadata[TileLayerMetadata[K]]
val layer: TileLayerRDD[SpatialKey] = ... /* Result of previous work */
val viewshed: TileLayerRDD[SpatialKey] = layer.viewshed(Seq(point))Sparkified Euclidean Distance
We use Euclidean Distance to render a collection of points into a
heatmap of proximities of some area. Say, of two roads crossing:
Prior to GeoTrellis 1.2, this was possible at the individual Tile level but not the Layer (RDD) level. Now it is.
/* Result of previous work. Potentially millions of points per SpatialKey. */
val points: RDD[(SpatialKey, Array[Coordinate])] = ...
val layout: LayoutDefinition = ... /* The definition of your grid */
val layer: RDD[(SpatialKey, Tile)] = points.euclideanDistance(layout)Polygonal Summaries over Time
The following was possible prior to GeoTrellis 1.2:
val layer: TileLayerRDD[SpatialKey] = ...
val polygon: Polgyon = ...
/* The maximum value within some Polygon overlaid on a Tile layer */
val summary: Double = layer.polygonalMaxDouble(polygon)The above is also now possible for layers keyed by SpaceTimeKey to
form a "time series":
val layer: TileLayerRDD[SpaceTimeKey] = ...
val polygon: MultiPolygon = ...
/* The maximum value within some Polygonal area at each time slice */
val summary: Map[ZonedDateTime, Double] = layer.maxSeries(polygon)
Overzooming ValueReader
A GeoTrellis ValueReader connects to some layer catalog and lets you read individual values (usually Tiles):
import geotrellis.spark.io.s3._
val store: AttributeStore = ...
val reader: Reader[SpatialKey, Tile] = S3ValueReader(store).reader(LayerId("my-catalog", 10))
val tile: Tile = reader.read(SpatialKey(10, 10))However .reader is limited to zoom levels that actually exist for the given layer. Now you can use .overzoomingReader to go as deep as you like:
import geotrellis.raster.resample._
val reader: Reader[SpatialKey, Tile] =
S3ValueReader(store).overzoomingReader(LayerId("my-catalog", 20), Average)
val tile: Tile = reader.read(SpatialKey(1000, 1000))Regridding a Tile Layer
Have you ever wanted to "redraw" a grid over an established GeoTrellis layer? Say, this 16-tile Layer into a 4-tile one, both of 1024x1024 total pixels:
Prior to GeoTrellis 1.2, there was no official way to do this. Now you can use .regrid:
/* The result of some previous work. Say each Tile is 256x256. */
val layer: TileLayerRDD[SpatialKey] = ...
/* "Recut" the tiles so that each one is now 512x512.
* No pixels are gained or lost, save some NODATA on the bottom
* and right edges that may appear for padding purposes.
*/
val regridded: TileLayerRDD[SpatialKey] = layer.regrid(512)You can also regrid to non-rectangular sizes:
val regridded: TileLayerRDD[SpatialKey] = layer.regrid(tileCols = 100, tileRows = 300)Robust Layer Querying
It's common to find a subset of Tiles in a layer that are touched by some given Polygon:
val poly: Polygon = ???
val rdd: TileLayerRDD[SpatialKey] =
layerReader
.query[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](Layer("name", zoom))
.where(Intersects(poly))
.resultNow you can perform this same operation with Line, MultiLine, and even (Polygon, CRS) to ensure that your Layer and Geometry always exist in the same projection.
Improved Tile ASCII Art
Sometimes you just want to visualize a Tile without going through the song-and-dance of rendering it to a .png. The existing Tile.asciiDraw method kind of does that, except its output is all in numbers.
The new Tile.renderAscii: Palette => String method fulfills your heart's desire:
import geotrellis.raster._
import geotrellis.raster.io.geotiff._
import geotrellis.raster.render.ascii._
val tile: Tile = SinglebandGeoTiff("path/to/tiff.tiff").tile
// println(tile.renderAscii()) // the default
println(tile.renderAscii(AsciiArtEncoder.Palette.STIPLED))
▚▖
▚▚▜▚▚
▚▖▚▜▚▖▚▚
▜▚▚▚▜▚█▚▜▚█▚
█▚▜▖▜▖▚▚█▚▚▜▚█▖
▚▚█▚▜▚▚▚▚▚▚▚▜▚▚▚▚▚
▚▚▖▚▚▚▚▚█▜▚▚▜▚▚▖▚▖▚▖▚
▚▚▚▚█▚▚▚▚▚██▚▚▚▜▖▖██▚▚▜▚
▚▚█▚▚▚▚▚▚▚▜▚▚▚▚▚▚▜▚█▚▚▚▚▚▚▚
█▚▚▖▚█▚▜▚▚▚▚▖▚▚▚▚▚▚▚▚▚▚▜▚▚▚▚▚▚▖
█▚▚▚▜▚▖▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚▚██▖▜▚█▚▚▚
█▚▚██▚▚▚▚▚▚▚▚▖▚▚▚▚▚▚▚▚█▚▚▚▚▚▚▖▖▖▚▚▚▚
█▜▚▚██▜▚▚▚▜▖▚▚▜▚█▜▚▚▚▜▚▖▚▜▚█▚▚▖▚▚▖▚▚▖▖▚▚
▚▚█▚▚▚█▚██▚▚▚▚▚▚▚▚▜▚▚█▜▚▖█▚▚▚▜▚▚▚▚▚▚▜▚█▚█
█▚▜▚▜▚█▚▜▚▚▜▚█▚▚▚▚▚▚▚▚▚▚▚▖▚▖▚▚▖▚█▚█▚▚▚▖█▚
████▚███▚▚▚▚██▚▚▚█▜▚▚▖▚▚▚▖▖▚▚▚▚▚▚▚▚█▚▜▖█
▖█▜▚█▚██▜▖▜▜█▜▜█▜▚▚▚▚▚█▖▚▚▚▚█▚▚▚▚▚▚▜▚▚█▖▜
▚▖██▚▜▚█▚▚▜▜█▜▜▜██▚▚▚▚█▚▚▚▜▖▚▚█▚▖▚▜▚▚▚▖▚█
█▚▚▚▚▜▚██▖██▜▚▚█▚▚▖▚▚▜▚▖▚▖▚▚▚▚▚▖▚▚▖▖▖▚▖▚
▚▚▚█▚▚▚▚▚█▜▚▚████▚█▚▚▚█▚▖▚▚▚▖▚▚█▚▚▖▚▚▚▖▖▖
▚▚▚█▚▚▚▖▖▚▜█▜██▜██▚▚▖██▜▚▜▚█▚▚▚▚▚▚▚▚▖▖▜██
▚▚▚▚▜█▚▚▚▚▚█████▚▜██▚██▚▚▚▚▜▚▖▚█▚▚▖▚▖▚▚█
▚▚▜▚▚▚▚▜▚▜▚▚▚▚▜▚█▚▜█▚██▚██▚▚▚▚▖▚▚▚▚▖▖▚▚▖█
▚▜▚▜▚▚▚▚▚▚█▚▚▚▚▚██▜▜▜███▖▚▚▜█▚▚▖▚█▚▚█▚▖▚
▚▜▚▚▚▚▚▚▚▚▚▚▜▜▜▚▚▖▚▖▚▚▜▜██▜▚██▚▚▚▚▚▚▖▜█▚
▚▚▖▚▚█▚█▚▚▚█▚▖▚▚▚█▚▚▚▚▚▜██▚█▜▚█▚▜▚▚███▜█▜
▚▚▚▜▚▚▚▚▚▚▚▚▚▚▚▖█▚█▚▚▜█▜█▜█▜▚▖▚▚▚██▜▜█▚▜
▚▚▚▚▜▚▚▚▚▚▚▜▚▚▚▚▚▚▖▚█▜▖▖█▚▖▜▖▚▖█▚▖█▚▚▜▚█
▚▚█▚▚█...


