Skip to content

Commit 37e8aba

Browse files
committed
Merge remote-tracking branch 'locationtech/develop' into feature/python-raster-reader-arg-refactor
Signed-off-by: Jason T. Brown <[email protected]>
2 parents 902e794 + ba3d30d commit 37e8aba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1295
-542
lines changed

build.sbt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,28 @@ lazy val experimental = project
129129

130130
lazy val docs = project
131131
.dependsOn(core, datasource, pyrasterframes)
132-
.enablePlugins(SiteScaladocPlugin, ParadoxPlugin, GhpagesPlugin, ScalaUnidocPlugin)
132+
.enablePlugins(SiteScaladocPlugin, ParadoxPlugin, ParadoxMaterialThemePlugin, GhpagesPlugin, ScalaUnidocPlugin)
133133
.settings(
134134
apiURL := Some(url("http://rasterframes.io/latest/api")),
135135
autoAPIMappings := true,
136136
ghpagesNoJekyll := true,
137137
ScalaUnidoc / siteSubdirName := "latest/api",
138138
paradox / siteSubdirName := ".",
139139
paradoxProperties ++= Map(
140-
"github.base_url" -> "https://github.com/locationtech/rasterframes",
141140
"version" -> version.value,
142-
"scaladoc.org.apache.spark.sql.rf" -> "http://rasterframes.io/latest"
141+
"scaladoc.org.apache.spark.sql.rf" -> "http://rasterframes.io/latest",
142+
"github.base_url" -> ""
143143
),
144144
paradoxNavigationExpandDepth := Some(3),
145-
paradoxTheme := Some(builtinParadoxTheme("generic")),
145+
Compile / paradoxMaterialTheme ~= { _
146+
.withRepository(uri("https://github.com/locationtech/rasterframes"))
147+
.withCustomStylesheet("assets/custom.css")
148+
.withCopyright("""&copy; 2017-2019 <a href="https://astraea.earth">Astraea</a>, Inc. All rights reserved.""")
149+
.withLogo("assets/images/RF-R.svg")
150+
.withFavicon("assets/images/RasterFrames_32x32.ico")
151+
.withColor("blue-grey", "light-blue")
152+
.withGoogleAnalytics("UA-106630615-1")
153+
},
146154
makeSite := makeSite
147155
.dependsOn(Compile / unidoc)
148156
.dependsOn((Compile / paradox)
@@ -157,6 +165,8 @@ lazy val docs = project
157165
addMappingsToSiteDir(Compile / paradox / mappings, paradox / siteSubdirName)
158166
)
159167

168+
//ParadoxMaterialThemePlugin.paradoxMaterialThemeSettings(Paradox)
169+
160170
lazy val bench = project
161171
.dependsOn(core % "compile->test")
162172
.settings(publish / skip := true)

core/src/main/scala/org/locationtech/rasterframes/RasterFunctions.scala

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package org.locationtech.rasterframes
2323
import geotrellis.proj4.CRS
2424
import geotrellis.raster.mapalgebra.local.LocalTileBinaryOp
25+
import geotrellis.raster.render.ColorRamp
2526
import geotrellis.raster.{CellType, Tile}
2627
import geotrellis.vector.Extent
2728
import org.apache.spark.annotation.Experimental
@@ -34,6 +35,7 @@ import org.locationtech.rasterframes.expressions.aggregates._
3435
import org.locationtech.rasterframes.expressions.generators._
3536
import org.locationtech.rasterframes.expressions.localops._
3637
import org.locationtech.rasterframes.expressions.tilestats._
38+
import org.locationtech.rasterframes.expressions.transformers.RenderPNG.{RenderCompositePNG, RenderColorRampPNG}
3739
import org.locationtech.rasterframes.expressions.transformers._
3840
import org.locationtech.rasterframes.model.TileDimensions
3941
import org.locationtech.rasterframes.stats._
@@ -81,6 +83,10 @@ trait RasterFunctions {
8183
def rf_assemble_tile(columnIndex: Column, rowIndex: Column, cellData: Column, tileCols: Int, tileRows: Int, ct: CellType): TypedColumn[Any, Tile] =
8284
rf_convert_cell_type(TileAssembler(columnIndex, rowIndex, cellData, lit(tileCols), lit(tileRows)), ct).as(cellData.columnName).as[Tile](singlebandTileEncoder)
8385

86+
/** Create a Tile from a column of cell data with location indexes and perform cell conversion. */
87+
def rf_assemble_tile(columnIndex: Column, rowIndex: Column, cellData: Column, tileCols: Int, tileRows: Int): TypedColumn[Any, Tile] =
88+
TileAssembler(columnIndex, rowIndex, cellData, lit(tileCols), lit(tileRows))
89+
8490
/** Create a Tile from a column of cell data with location indexes. */
8591
def rf_assemble_tile(columnIndex: Column, rowIndex: Column, cellData: Column, tileCols: Column, tileRows: Column): TypedColumn[Any, Tile] =
8692
TileAssembler(columnIndex, rowIndex, cellData, tileCols, tileRows)
@@ -94,6 +100,18 @@ trait RasterFunctions {
94100
/** Change the Tile's cell type */
95101
def rf_convert_cell_type(col: Column, cellTypeName: String): Column = SetCellType(col, cellTypeName)
96102

103+
/** Change the Tile's cell type */
104+
def rf_convert_cell_type(col: Column, cellType: Column): Column = SetCellType(col, cellType)
105+
106+
/** Change the interpretation of the Tile's cell values according to specified CellType */
107+
def rf_interpret_cell_type_as(col: Column, cellType: CellType): Column = InterpretAs(col, cellType)
108+
109+
/** Change the interpretation of the Tile's cell values according to specified CellType */
110+
def rf_interpret_cell_type_as(col: Column, cellTypeName: String): Column = InterpretAs(col, cellTypeName)
111+
112+
/** Change the interpretation of the Tile's cell values according to specified CellType */
113+
def rf_interpret_cell_type_as(col: Column, cellType: Column): Column = InterpretAs(col, cellType)
114+
97115
/** Resample tile to different size based on scalar factor or tile whose dimension to match. Scalar less
98116
* than one will downsample tile; greater than one will upsample. Uses nearest-neighbor. */
99117
def rf_resample[T: Numeric](tileCol: Column, factorValue: T) = Resample(tileCol, factorValue)
@@ -317,12 +335,24 @@ trait RasterFunctions {
317335
ReprojectGeometry(sourceGeom, srcCRSCol, dstCRSCol)
318336

319337
/** Render Tile as ASCII string, for debugging purposes. */
320-
def rf_render_ascii(col: Column): TypedColumn[Any, String] =
321-
DebugRender.RenderAscii(col)
338+
def rf_render_ascii(tile: Column): TypedColumn[Any, String] =
339+
DebugRender.RenderAscii(tile)
322340

323341
/** Render Tile cell values as numeric values, for debugging purposes. */
324-
def rf_render_matrix(col: Column): TypedColumn[Any, String] =
325-
DebugRender.RenderMatrix(col)
342+
def rf_render_matrix(tile: Column): TypedColumn[Any, String] =
343+
DebugRender.RenderMatrix(tile)
344+
345+
/** Converts tiles in a column into PNG encoded byte array, using given ColorRamp to assign values to colors. */
346+
def rf_render_png(tile: Column, colors: ColorRamp): TypedColumn[Any, Array[Byte]] =
347+
RenderColorRampPNG(tile, colors)
348+
349+
/** Converts columns of tiles representing RGB channels into a PNG encoded byte array. */
350+
def rf_render_png(red: Column, green: Column, blue: Column): TypedColumn[Any, Array[Byte]] =
351+
RenderCompositePNG(red, green, blue)
352+
353+
/** Converts columns of tiles representing RGB channels into a single RGB packaged tile. */
354+
def rf_rgb_composite(red: Column, green: Column, blue: Column): Column =
355+
RGBComposite(red, green, blue)
326356

327357
/** Cellwise less than value comparison between two tiles. */
328358
def rf_local_less(left: Column, right: Column): Column = Less(left, right)
@@ -359,6 +389,12 @@ trait RasterFunctions {
359389
/** Cellwise inequality comparison between a tile and a scalar. */
360390
def rf_local_unequal[T: Numeric](tileCol: Column, value: T): Column = Unequal(tileCol, value)
361391

392+
/** Return a tile with ones where the input is NoData, otherwise zero */
393+
def rf_local_no_data(tileCol: Column): Column = Undefined(tileCol)
394+
395+
/** Return a tile with zeros where the input is NoData, otherwise one*/
396+
def rf_local_data(tileCol: Column): Column = Defined(tileCol)
397+
362398
/** Round cell values to nearest integer without chaning cell type. */
363399
def rf_round(tileCol: Column): Column = Round(tileCol)
364400

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This software is licensed under the Apache 2 license, quoted below.
3+
*
4+
* Copyright 2019 Astraea, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
7+
* use this file except in compliance with the License. You may obtain a copy of
8+
* the License at
9+
*
10+
* [http://www.apache.org/licenses/LICENSE-2.0]
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15+
* License for the specific language governing permissions and limitations under
16+
* the License.
17+
*
18+
* SPDX-License-Identifier: Apache-2.0
19+
*
20+
*/
21+
22+
package org.locationtech.rasterframes.expressions.localops
23+
24+
import geotrellis.raster.Tile
25+
import org.apache.spark.sql.Column
26+
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
27+
import org.apache.spark.sql.catalyst.expressions.{Expression, ExpressionDescription}
28+
import org.locationtech.rasterframes.expressions.{NullToValue, UnaryLocalRasterOp}
29+
30+
@ExpressionDescription(
31+
usage = "_FUNC_(tile) - Return a tile with zeros where the input is NoData, otherwise one.",
32+
arguments = """
33+
Arguments:
34+
* tile - tile column to inspect""",
35+
examples = """
36+
Examples:
37+
> SELECT _FUNC_(tile);
38+
..."""
39+
)
40+
case class Defined(child: Expression) extends UnaryLocalRasterOp
41+
with NullToValue with CodegenFallback {
42+
override def nodeName: String = "rf_local_data"
43+
override def na: Any = null
44+
override protected def op(child: Tile): Tile = child.localDefined()
45+
}
46+
object Defined{
47+
def apply(tile: Column): Column = new Column(Defined(tile.expr))
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This software is licensed under the Apache 2 license, quoted below.
3+
*
4+
* Copyright 2019 Astraea, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
7+
* use this file except in compliance with the License. You may obtain a copy of
8+
* the License at
9+
*
10+
* [http://www.apache.org/licenses/LICENSE-2.0]
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15+
* License for the specific language governing permissions and limitations under
16+
* the License.
17+
*
18+
* SPDX-License-Identifier: Apache-2.0
19+
*
20+
*/
21+
22+
package org.locationtech.rasterframes.expressions.localops
23+
24+
import geotrellis.raster.Tile
25+
import org.apache.spark.sql.Column
26+
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
27+
import org.apache.spark.sql.catalyst.expressions.{Expression, ExpressionDescription}
28+
import org.locationtech.rasterframes.expressions.{NullToValue, UnaryLocalRasterOp}
29+
30+
@ExpressionDescription(
31+
usage = "_FUNC_(tile) - Return a tile with ones where the input is NoData, otherwise zero.",
32+
arguments = """
33+
Arguments:
34+
* tile - tile column to inspect""",
35+
examples = """
36+
Examples:
37+
> SELECT _FUNC_(tile);
38+
..."""
39+
)
40+
case class Undefined(child: Expression) extends UnaryLocalRasterOp
41+
with NullToValue with CodegenFallback {
42+
override def nodeName: String = "rf_local_no_data"
43+
override def na: Any = null
44+
override protected def op(child: Tile): Tile = child.localUndefined()
45+
}
46+
object Undefined{
47+
def apply(tile: Column): Column = new Column(Undefined(tile.expr))
48+
}

core/src/main/scala/org/locationtech/rasterframes/expressions/package.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ package object expressions {
6868
registry.registerExpression[ExplodeTiles]("rf_explode_tiles")
6969
registry.registerExpression[GetCellType]("rf_cell_type")
7070
registry.registerExpression[SetCellType]("rf_convert_cell_type")
71+
registry.registerExpression[InterpretAs]("rf_interpret_cell_type_as")
7172
registry.registerExpression[SetNoDataValue]("rf_with_no_data")
7273
registry.registerExpression[GetDimensions]("rf_dimensions")
7374
registry.registerExpression[ExtentToGeometry]("st_geometry")
@@ -86,6 +87,8 @@ package object expressions {
8687
registry.registerExpression[GreaterEqual]("rf_local_greater_equal")
8788
registry.registerExpression[Equal]("rf_local_equal")
8889
registry.registerExpression[Unequal]("rf_local_unequal")
90+
registry.registerExpression[Undefined]("rf_local_no_data")
91+
registry.registerExpression[Defined]("rf_local_data")
8992
registry.registerExpression[Sum]("rf_tile_sum")
9093
registry.registerExpression[Round]("rf_round")
9194
registry.registerExpression[Abs]("rf_abs")
@@ -128,6 +131,9 @@ package object expressions {
128131

129132
registry.registerExpression[DebugRender.RenderAscii]("rf_render_ascii")
130133
registry.registerExpression[DebugRender.RenderMatrix]("rf_render_matrix")
134+
registry.registerExpression[RenderPNG.RenderCompositePNG]("rf_render_png")
135+
registry.registerExpression[RGBComposite]("rf_rgb_composite")
136+
131137
registry.registerExpression[transformers.ReprojectGeometry]("st_reproject")
132138
}
133139
}

core/src/main/scala/org/locationtech/rasterframes/expressions/transformers/DebugRender.scala

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,29 @@
2121

2222
package org.locationtech.rasterframes.expressions.transformers
2323

24-
import org.locationtech.rasterframes.expressions.UnaryRasterOp
25-
import org.locationtech.rasterframes.util.TileAsMatrix
26-
import geotrellis.raster.Tile
2724
import geotrellis.raster.render.ascii.AsciiArtEncoder
25+
import geotrellis.raster.{Tile, isNoData}
2826
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
2927
import org.apache.spark.sql.catalyst.expressions.{Expression, ExpressionDescription}
3028
import org.apache.spark.sql.types.{DataType, StringType}
3129
import org.apache.spark.sql.{Column, TypedColumn}
3230
import org.apache.spark.unsafe.types.UTF8String
31+
import org.locationtech.rasterframes.expressions.UnaryRasterOp
3332
import org.locationtech.rasterframes.model.TileContext
33+
import spire.syntax.cfor.cfor
3434

3535
abstract class DebugRender(asciiArt: Boolean) extends UnaryRasterOp
36-
with CodegenFallback with Serializable {
37-
override def dataType: DataType = StringType
36+
with CodegenFallback with Serializable {
37+
import org.locationtech.rasterframes.expressions.transformers.DebugRender.TileAsMatrix
38+
override def dataType: DataType = StringType
3839

39-
override protected def eval(tile: Tile, ctx: Option[TileContext]): Any = {
40-
UTF8String.fromString(if (asciiArt)
41-
s"\n${tile.renderAscii(AsciiArtEncoder.Palette.NARROW)}\n"
42-
else
43-
s"\n${tile.renderMatrix(6)}\n"
44-
)
45-
}
40+
override protected def eval(tile: Tile, ctx: Option[TileContext]): Any = {
41+
UTF8String.fromString(if (asciiArt)
42+
s"\n${tile.renderAscii(AsciiArtEncoder.Palette.NARROW)}\n"
43+
else
44+
s"\n${tile.renderMatrix(6)}\n"
45+
)
46+
}
4647
}
4748

4849
object DebugRender {
@@ -75,4 +76,29 @@ object DebugRender {
7576
def apply(tile: Column): TypedColumn[Any, String] =
7677
new Column(RenderMatrix(tile.expr)).as[String]
7778
}
79+
80+
implicit class TileAsMatrix(val tile: Tile) extends AnyVal {
81+
def renderMatrix(significantDigits: Int): String = {
82+
val ND = s"%${significantDigits+5}s".format(Double.NaN)
83+
val fmt = s"% ${significantDigits+5}.${significantDigits}g"
84+
val buf = new StringBuilder("[")
85+
cfor(0)(_ < tile.rows, _ + 1) { row =>
86+
if(row > 0) buf.append(' ')
87+
buf.append('[')
88+
cfor(0)(_ < tile.cols, _ + 1) { col =>
89+
val v = tile.getDouble(col, row)
90+
if (isNoData(v)) buf.append(ND)
91+
else buf.append(fmt.format(v))
92+
93+
if (col < tile.cols - 1)
94+
buf.append(',')
95+
}
96+
buf.append(']')
97+
if (row < tile.rows - 1)
98+
buf.append(",\n")
99+
}
100+
buf.append("]")
101+
buf.toString()
102+
}
103+
}
78104
}

0 commit comments

Comments
 (0)