Skip to content

Commit 86c69c0

Browse files
committed
Merge branch 'release/0.10.1'
2 parents 14fe14b + 8025286 commit 86c69c0

File tree

38 files changed

+1179
-342
lines changed

38 files changed

+1179
-342
lines changed
File renamed without changes.

build.sbt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,15 @@ lazy val datasource = project
120120
moduleName := "rasterframes-datasource",
121121
libraryDependencies ++= Seq(
122122
compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full),
123+
compilerPlugin("org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full),
123124
sttpCatsCe2,
124125
stac4s,
126+
framelessRefined excludeAll ExclusionRule(organization = "com.github.mpilquist"),
125127
geotrellis("s3").value excludeAll ExclusionRule(organization = "com.github.mpilquist"),
126128
spark("core").value % Provided,
127129
spark("mllib").value % Provided,
128-
spark("sql").value % Provided
130+
spark("sql").value % Provided,
131+
`better-files`
129132
),
130133
Compile / console / scalacOptions ~= { _.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports")) },
131134
Test / console / scalacOptions ~= { _.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports")) },
@@ -173,7 +176,7 @@ lazy val docs = project
173176
Compile / paradoxMaterialTheme ~= { _
174177
.withRepository(uri("https://github.com/locationtech/rasterframes"))
175178
.withCustomStylesheet("assets/custom.css")
176-
.withCopyright("""&copy; 2017-2019 <a href="https://astraea.earth">Astraea</a>, Inc. All rights reserved.""")
179+
.withCopyright("""&copy; 2017-2021 <a href="https://astraea.earth">Astraea</a>, Inc. All rights reserved.""")
177180
.withLogo("assets/images/RF-R.svg")
178181
.withFavicon("assets/images/RasterFrames_32x32.ico")
179182
.withColor("blue-grey", "light-blue")

core/src/main/scala/org/apache/spark/sql/rf/package.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ package object rf {
5656

5757
/** Lookup the registered Catalyst UDT for the given Scala type. */
5858
def udtOf[T >: Null: TypeTag]: UserDefinedType[T] =
59-
UDTRegistration.getUDTFor(typeTag[T].tpe.toString).map(_.newInstance().asInstanceOf[UserDefinedType[T]])
59+
UDTRegistration.getUDTFor(typeTag[T].tpe.toString).map(_.getDeclaredConstructor().newInstance().asInstanceOf[UserDefinedType[T]])
6060
.getOrElse(throw new IllegalArgumentException(typeTag[T].tpe + " doesn't have a corresponding UDT"))
6161

6262
/** Creates a Catalyst expression for flattening the fields in a struct into columns. */

core/src/main/scala/org/locationtech/rasterframes/encoders/StandardEncoders.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import org.locationtech.geomesa.spark.jts.encoders.SpatialEncoders
3333
import org.locationtech.rasterframes.model.{CellContext, LongExtent, TileContext, TileDataContext}
3434
import frameless.TypedEncoder
3535
import geotrellis.raster.mapalgebra.focal.{Kernel, Neighborhood, TargetCell}
36+
import org.locationtech.rasterframes.ref.RFRasterSource
37+
import org.locationtech.rasterframes.tiles.ProjectedRasterTile
3638

3739
import java.net.URI
3840
import java.sql.Timestamp
@@ -45,14 +47,14 @@ trait StandardEncoders extends SpatialEncoders with TypedEncoders {
4547
implicit def optionalEncoder[T: TypedEncoder]: ExpressionEncoder[Option[T]] = typedExpressionEncoder[Option[T]]
4648

4749
implicit lazy val strMapEncoder: ExpressionEncoder[Map[String, String]] = ExpressionEncoder()
48-
implicit lazy val crsExpressionEncoder: ExpressionEncoder[CRS] = ExpressionEncoder()
4950
implicit lazy val projectedExtentEncoder: ExpressionEncoder[ProjectedExtent] = ExpressionEncoder()
5051
implicit lazy val temporalProjectedExtentEncoder: ExpressionEncoder[TemporalProjectedExtent] = ExpressionEncoder()
5152
implicit lazy val timestampEncoder: ExpressionEncoder[Timestamp] = ExpressionEncoder()
5253
implicit lazy val cellStatsEncoder: ExpressionEncoder[CellStatistics] = ExpressionEncoder()
5354
implicit lazy val cellHistEncoder: ExpressionEncoder[CellHistogram] = ExpressionEncoder()
5455
implicit lazy val localCellStatsEncoder: ExpressionEncoder[LocalCellStatistics] = ExpressionEncoder()
5556

57+
implicit lazy val crsExpressionEncoder: ExpressionEncoder[CRS] = typedExpressionEncoder
5658
implicit lazy val uriEncoder: ExpressionEncoder[URI] = typedExpressionEncoder[URI]
5759
implicit lazy val neighborhoodEncoder: ExpressionEncoder[Neighborhood] = typedExpressionEncoder[Neighborhood]
5860
implicit lazy val targetCellEncoder: ExpressionEncoder[TargetCell] = typedExpressionEncoder[TargetCell]
@@ -78,6 +80,11 @@ trait StandardEncoders extends SpatialEncoders with TypedEncoders {
7880

7981
implicit lazy val tileEncoder: ExpressionEncoder[Tile] = typedExpressionEncoder
8082
implicit def rasterEncoder[T <: CellGrid[Int]: TypedEncoder]: ExpressionEncoder[Raster[T]] = typedExpressionEncoder[Raster[T]]
83+
84+
// Intentionally not implicit, defined as implicit in the ProjectedRasterTile companion object
85+
lazy val projectedRasterTileEncoder: ExpressionEncoder[ProjectedRasterTile] = typedExpressionEncoder
86+
// Intentionally not implicit, defined as implicit in the RFRasterSource companion object
87+
lazy val rfRasterSourceEncoder: ExpressionEncoder[RFRasterSource] = typedExpressionEncoder
8188
}
8289

8390
object StandardEncoders extends StandardEncoders

core/src/main/scala/org/locationtech/rasterframes/encoders/TypedEncoders.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
1010
import org.apache.spark.sql.catalyst.util.QuantileSummaries
1111
import org.apache.spark.sql.rf.{CrsUDT, RasterSourceUDT, TileUDT}
1212
import org.locationtech.jts.geom.Envelope
13+
import org.locationtech.rasterframes.ref.RFRasterSource
14+
import org.locationtech.rasterframes.tiles.ProjectedRasterTile
1315
import org.locationtech.rasterframes.util.{FocalNeighborhood, FocalTargetCell, KryoSupport}
1416

1517
import java.net.URI
@@ -23,6 +25,8 @@ trait TypedEncoders {
2325
implicit val tileUDT = new TileUDT
2426
implicit val rasterSourceUDT = new RasterSourceUDT
2527

28+
implicit val crsTypedEncoder: TypedEncoder[CRS] = TypedEncoder.usingUserDefinedType[CRS]
29+
2630
implicit val cellTypeInjection: Injection[CellType, String] = Injection(_.toString, CellType.fromName)
2731
implicit val cellTypeTypedEncoder: TypedEncoder[CellType] = TypedEncoder.usingInjection[CellType, String]
2832

@@ -89,7 +93,20 @@ trait TypedEncoders {
8993
implicit val tileTypedEncoder: TypedEncoder[Tile] = TypedEncoder.usingUserDefinedType[Tile]
9094
implicit def rasterTileTypedEncoder[T <: CellGrid[Int]: TypedEncoder]: TypedEncoder[Raster[T]] = TypedEncoder.usingDerivation
9195

96+
// Derivation is done through frameless to trigger RasterSourceUDT load
97+
implicit val rfRasterSourceTypedEncoder: TypedEncoder[RFRasterSource] = TypedEncoder.usingUserDefinedType[RFRasterSource]
98+
9299
implicit val kernelTypedEncoder: TypedEncoder[Kernel] = TypedEncoder.usingDerivation
100+
101+
// Derivation is done through frameless to trigger the TileUDT and CrsUDT load
102+
implicit val projectedRasterTileTypedEncoder: TypedEncoder[ProjectedRasterTile] =
103+
ManualTypedEncoder.newInstance[ProjectedRasterTile](
104+
fields = List(
105+
RecordEncoderField(0, "tile", TypedEncoder[Tile]),
106+
RecordEncoderField(1, "extent", TypedEncoder[Extent]),
107+
RecordEncoderField(2, "crs", TypedEncoder[CRS])
108+
)
109+
)
93110
}
94111

95112
object TypedEncoders extends TypedEncoders

core/src/main/scala/org/locationtech/rasterframes/expressions/aggregates/ProjectedLayerMetadataAggregate.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import org.apache.spark.sql.types.{DataType, StructType}
3434
import org.apache.spark.sql.{Column, Row, TypedColumn}
3535

3636
class ProjectedLayerMetadataAggregate(destCRS: CRS, destDims: Dimensions[Int]) extends UserDefinedAggregateFunction {
37+
3738
import ProjectedLayerMetadataAggregate._
3839

3940
def inputSchema: StructType = InputRecord.inputRecordEncoder.schema
@@ -47,10 +48,10 @@ class ProjectedLayerMetadataAggregate(destCRS: CRS, destDims: Dimensions[Int]) e
4748
def initialize(buffer: MutableAggregationBuffer): Unit = ()
4849

4950
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
50-
if(!input.isNullAt(0)) {
51+
if (!input.isNullAt(0)) {
5152
val in = input.as[InputRecord]
5253

53-
if(buffer.isNullAt(0)) {
54+
if (buffer.isNullAt(0)) {
5455
in.toBufferRecord(destCRS).write(buffer)
5556
} else {
5657
val br = buffer.as[BufferRecord]
@@ -71,16 +72,15 @@ class ProjectedLayerMetadataAggregate(destCRS: CRS, destDims: Dimensions[Int]) e
7172
case _ => ()
7273
}
7374

74-
def evaluate(buffer: Row): Any = {
75-
val buf = buffer.as[BufferRecord]
76-
if (buf.isEmpty) throw new IllegalArgumentException("Can not collect metadata from empty data frame.")
75+
def evaluate(buffer: Row): Any =
76+
Option(buffer).map(_.as[BufferRecord]).filter(!_.isEmpty).map(buf => {
77+
val re = RasterExtent(buf.extent, buf.cellSize)
78+
val layout = LayoutDefinition(re, destDims.cols, destDims.rows)
7779

78-
val re = RasterExtent(buf.extent, buf.cellSize)
79-
val layout = LayoutDefinition(re, destDims.cols, destDims.rows)
80+
val kb = KeyBounds(layout.mapTransform(buf.extent))
81+
TileLayerMetadata(buf.cellType, layout, buf.extent, destCRS, kb).toRow
8082

81-
val kb = KeyBounds(layout.mapTransform(buf.extent))
82-
TileLayerMetadata(buf.cellType, layout, buf.extent, destCRS, kb).toRow
83-
}
83+
}).getOrElse(throw new IllegalArgumentException("Can not collect metadata from empty data frame."))
8484
}
8585

8686
object ProjectedLayerMetadataAggregate {

core/src/main/scala/org/locationtech/rasterframes/ref/RFRasterSource.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import geotrellis.vector.Extent
3131
import org.apache.hadoop.conf.Configuration
3232
import org.apache.spark.annotation.Experimental
3333
import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
34-
import org.apache.spark.sql.rf.RasterSourceUDT
34+
import org.locationtech.rasterframes.encoders.StandardEncoders
3535
import org.locationtech.rasterframes.model.TileContext
3636
import org.locationtech.rasterframes.{NOMINAL_TILE_DIMS, rfConfig}
3737

@@ -100,10 +100,7 @@ object RFRasterSource extends LazyLogging {
100100

101101
def cacheStats = rsCache.stats()
102102

103-
implicit def rsEncoder: ExpressionEncoder[RFRasterSource] = {
104-
RasterSourceUDT // Makes sure UDT is registered first
105-
ExpressionEncoder()
106-
}
103+
implicit lazy val rsEncoder: ExpressionEncoder[RFRasterSource] = StandardEncoders.rfRasterSourceEncoder
107104

108105
def apply(source: URI): RFRasterSource =
109106
rsCache.get(

core/src/main/scala/org/locationtech/rasterframes/tiles/ProjectedRasterTile.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import geotrellis.vector.{Extent, ProjectedExtent}
2727
import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
2828
import org.locationtech.rasterframes.ref.ProjectedRasterLike
2929
import org.apache.spark.sql.catalyst.DefinedByConstructorParams
30+
import org.locationtech.rasterframes.encoders.StandardEncoders
3031

3132
/**
3233
* A Tile that's also like a ProjectedRaster, with delayed evaluation support.
@@ -58,5 +59,6 @@ object ProjectedRasterTile {
5859

5960
def unapply(prt: ProjectedRasterTile): Option[(Tile, Extent, CRS)] = Some((prt.tile, prt.extent, prt.crs))
6061

61-
implicit lazy val projectedRasterTileEncoder: ExpressionEncoder[ProjectedRasterTile] = ExpressionEncoder()
62+
implicit lazy val projectedRasterTileEncoder: ExpressionEncoder[ProjectedRasterTile] =
63+
StandardEncoders.projectedRasterTileEncoder
6264
}

core/src/test/scala/org/locationtech/rasterframes/expressions/SFCIndexerSpec.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ package org.locationtech.rasterframes.expressions
2424
import geotrellis.proj4.{CRS, LatLng, WebMercator}
2525
import geotrellis.raster.CellType
2626
import geotrellis.vector._
27-
import org.apache.spark.sql.Encoders
2827
import org.apache.spark.sql.jts.JTSTypes
2928
import org.locationtech.geomesa.curve.{XZ2SFC, Z2SFC}
3029
import org.locationtech.rasterframes._
@@ -151,7 +150,6 @@ class SFCIndexerSpec extends TestEnvironment with Inspectors {
151150
val tile = TestData.randomTile(2, 2, CellType.fromName("uint8"))
152151
val prts = testExtents.map(reproject(crs)).map(ProjectedRasterTile(tile, _, crs))
153152

154-
implicit val enc = Encoders.tuple(ProjectedRasterTile.projectedRasterTileEncoder, Encoders.scalaInt)
155153
// The `id` here is to deal with Spark auto projecting single columns dataframes and needing to provide an encoder
156154
val df = prts.zipWithIndex.toDF("proj_raster", "id")
157155
withClue("XZ2") {

datasource/src/main/resources/META-INF/services/org.apache.spark.sql.sources.DataSourceRegister

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ org.locationtech.rasterframes.datasource.geotrellis.GeoTrellisCatalog
44
org.locationtech.rasterframes.datasource.raster.RasterSourceDataSource
55
org.locationtech.rasterframes.datasource.geojson.GeoJsonDataSource
66
org.locationtech.rasterframes.datasource.stac.api.StacApiDataSource
7+
org.locationtech.rasterframes.datasource.tiles.TilesDataSource
8+
org.locationtech.rasterframes.datasource.slippy.SlippyDataSource

0 commit comments

Comments
 (0)