Skip to content

Commit 2458e70

Browse files
authored
Merge pull request #73 from geotrellis/feature/test-nodata-handling
Test that ND values are respected by default interpreter
2 parents 36a4921 + d678ba0 commit 2458e70

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package geotrellis.server
2+
3+
import geotrellis.server.vlm._
4+
import geotrellis.contrib.vlm.gdal._
5+
import geotrellis.raster._
6+
import geotrellis.raster.io.geotiff.AutoHigherResolution
7+
import geotrellis.proj4._
8+
import geotrellis.spark.tiling._
9+
import geotrellis.contrib.vlm.TargetRegion
10+
import geotrellis.raster.resample.NearestNeighbor
11+
import geotrellis.vector.Extent
12+
13+
import com.azavea.maml.ast._
14+
import com.azavea.maml.ast.codec.tree._
15+
import com.azavea.maml.eval._
16+
import cats.effect._
17+
import cats.data.{NonEmptyList => NEL}
18+
import org.scalatest._
19+
20+
import scala.concurrent.ExecutionContext
21+
22+
23+
class NoDataHandlingTest extends FunSuite with Matchers with TileAsSourceImplicits {
24+
implicit val cs = cats.effect.IO.contextShift(ExecutionContext.global)
25+
26+
val expr = Addition(List(RasterVar("t1"), RasterVar("t2")))
27+
val eval = LayerTms.curried(expr, BufferingInterpreter.DEFAULT)
28+
29+
test("NODATA should be respected - user-defined, integer-based source celltype") {
30+
val t1 = IntUserDefinedNoDataArrayTile((1 to 100).toArray, 10, 10, IntUserDefinedNoDataCellType(1))
31+
val t2 = IntUserDefinedNoDataArrayTile((1 to 100).toArray, 10, 10, IntUserDefinedNoDataCellType(1))
32+
val paramMap = Map("t1" -> t1, "t2" -> t2)
33+
// We'll sample such that the bottom row (from 56 to 64) are excised from the result
34+
val res = eval(paramMap, 0, 0, 0).unsafeRunSync
35+
val tileRes = res.toOption.get.band(0)
36+
assert(tileRes.toArrayDouble.head.isNaN, s"Expected Double.NaN, got ${tileRes.toArrayDouble.head}")
37+
}
38+
39+
test("NODATA should be respected - different source celltypes") {
40+
val t1 = IntUserDefinedNoDataArrayTile((1 to 100).toArray, 10, 10, IntUserDefinedNoDataCellType(1))
41+
val t2 = DoubleUserDefinedNoDataArrayTile((1 to 100).map(_.toDouble).toArray, 10, 10, DoubleUserDefinedNoDataCellType(2.0))
42+
val paramMap = Map("t1" -> t1, "t2" -> t2)
43+
// We'll sample such that the bottom row (from 56 to 64) are excised from the result
44+
val res = eval(paramMap, 0, 0, 0).unsafeRunSync
45+
val tileRes = res.toOption.get.band(0)
46+
assert(tileRes.toArrayDouble.apply(0).isNaN, s"Expected Double.NaN, got ${tileRes.toArrayDouble.head}")
47+
}
48+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package geotrellis.server
2+
3+
import geotrellis.server.vlm._
4+
import geotrellis.contrib.vlm.gdal._
5+
import geotrellis.raster._
6+
import geotrellis.raster.io.geotiff.AutoHigherResolution
7+
import geotrellis.proj4._
8+
import geotrellis.spark.tiling._
9+
import geotrellis.contrib.vlm.TargetRegion
10+
import geotrellis.raster.resample.NearestNeighbor
11+
import geotrellis.vector.Extent
12+
13+
import com.azavea.maml.ast._
14+
import com.azavea.maml.ast.codec.tree._
15+
import com.azavea.maml.eval._
16+
import cats.effect._
17+
import cats.data.{NonEmptyList => NEL}
18+
import org.scalatest._
19+
20+
import scala.concurrent.ExecutionContext
21+
22+
// The entire point of this is to provide a *very unsafe* way to quickly test MAML evaluation
23+
// ZXY/Extent/CellSize/Etc are just ignored and the tile you pass in is what will be used
24+
trait TileAsSourceImplicits {
25+
val tmsLevels: Array[LayoutDefinition] = {
26+
val scheme = ZoomedLayoutScheme(WebMercator, 256)
27+
for (zoom <- 0 to 64) yield scheme.levelForZoom(zoom).layout
28+
}.toArray
29+
30+
implicit val extentReification: ExtentReification[Tile] = new ExtentReification[Tile] {
31+
def kind(self: Tile): MamlKind = MamlKind.Image
32+
def extentReification(self: Tile)(implicit contextShift: ContextShift[IO]): (Extent, CellSize) => IO[Literal] =
33+
(extent: Extent, cs: CellSize) => IO.pure(RasterLit(Raster(MultibandTile(self), extent)))
34+
}
35+
36+
implicit val nodeRasterExtents: HasRasterExtents[Tile] = new HasRasterExtents[Tile] {
37+
def rasterExtents(self: Tile)(implicit contextShift: ContextShift[IO]): IO[NEL[RasterExtent]] =
38+
IO.pure(NEL.of(RasterExtent(Extent(0, 0, 100, 100), 1.0, 1.0, self.cols, self.rows)))
39+
40+
}
41+
42+
implicit val tmsReification: TmsReification[Tile] = new TmsReification[Tile] {
43+
def kind(self: Tile): MamlKind = MamlKind.Image
44+
def tmsReification(self: Tile, buffer: Int)(implicit contextShift: ContextShift[IO]): (Int, Int, Int) => IO[Literal] = (z: Int, x: Int, y: Int) => {
45+
val extent = tmsLevels(z).mapTransform.keyToExtent(x, y)
46+
IO.pure(RasterLit(Raster(MultibandTile(self), extent)))
47+
}
48+
}
49+
50+
}
51+

0 commit comments

Comments
 (0)