Skip to content

Commit b45543b

Browse files
committed
Update docs and scala function api
Signed-off-by: Jason T. Brown <[email protected]>
1 parent 1c1c632 commit b45543b

File tree

4 files changed

+61
-16
lines changed

4 files changed

+61
-16
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,22 @@ trait RasterFunctions {
337337
def rf_inverse_mask_by_value(sourceTile: Column, maskTile: Column, maskValue: Int): TypedColumn[Any, Tile] =
338338
Mask.InverseMaskByValue(sourceTile, maskTile, lit(maskValue))
339339

340+
/** Applies a mask using bit values in the `mask_tile`. Working from the right, extract the bit at `bitPosition` from the `maskTile`. In all locations where these are equal to the `valueToMask`, the returned tile is set to NoData, else the original `dataTile` cell value. */
340341
def rf_mask_by_bit(dataTile: Column, maskTile: Column, bitPosition: Int, valueToMask: Boolean): Column =
341-
rf_mask_by_bit(dataTile, maskTile, lit(bitPosition), lit(bitPosition))
342+
rf_mask_by_bit(dataTile, maskTile, lit(bitPosition), lit(valueToMask))
342343

343-
def rf_mask_by_bit(dataTile: Column, maskTile: Column, bitPosition: Column, valueToMask: Column): Column = ???
344+
/** Applies a mask using bit values in the `mask_tile`. Working from the right, extract the bit at `bitPosition` from the `maskTile`. In all locations where these are equal to the `valueToMask`, the returned tile is set to NoData, else the original `dataTile` cell value. */
345+
def rf_mask_by_bit(dataTile: Column, maskTile: Column, bitPosition: Column, valueToMask: Column): Column =
346+
rf_mask_by_bits(dataTile, maskTile, bitPosition, lit(1), valueToMask)
347+
348+
/** Applies a mask from blacklisted bit values in the `mask_tile`. Working from the right, the bits from `start_bit` to `start_bit + num_bits` are @ref:[extracted](reference.md#rf_local_extract_bits) from cell values of the `mask_tile`. In all locations where these are in the `mask_values`, the returned tile is set to NoData; otherwise the original `tile` cell value is returned. */
349+
def rf_mask_by_bits(dataTile: Column, maskTile: Column, startBit: Column, numBits: Column, valuesToMask: Column): Column = {
350+
val bitMask = rf_local_extract_bits(maskTile, startBit, numBits)
351+
rf_mask_by_values(dataTile, bitMask, valuesToMask)
352+
}
344353

345-
def rf_mask_by_bits(dataTile: Column, maskTile: Column, startBit: Column, numBits: Column, valuesToMask: Column): Column = ???
346354

355+
/** Applies a mask from blacklisted bit values in the `mask_tile`. Working from the right, the bits from `start_bit` to `start_bit + num_bits` are @ref:[extracted](reference.md#rf_local_extract_bits) from cell values of the `mask_tile`. In all locations where these are in the `mask_values`, the returned tile is set to NoData; otherwise the original `tile` cell value is returned. */
347356
def rf_mask_by_bits(dataTile: Column, maskTile: Column, startBit: Int, numBits: Int, valuesToMask: Int*): Column = {
348357
import org.apache.spark.sql.functions.array
349358
val values = array(valuesToMask.map(lit):_*)

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,29 @@ case class ExtractBits(child1: Expression, child2: Expression, child3: Expressio
6767
implicit val tileSer = TileUDT.tileSerializer
6868
val (childTile, childCtx) = tileExtractor(child1.dataType)(row(input1))
6969

70-
val startBits = intArgExtractor(child2.dataType)(input2).value.toShort
70+
val startBits = intArgExtractor(child2.dataType)(input2).value
7171

72-
val numBits = intArgExtractor(child2.dataType)(input3).value.toShort
72+
val numBits = intArgExtractor(child2.dataType)(input3).value
7373

7474
childCtx match {
7575
case Some(ctx) => ctx.toProjectRasterTile(op(childTile, startBits, numBits)).toInternalRow
7676
case None => op(childTile, startBits, numBits).toInternalRow
7777
}
7878
}
7979

80-
protected def op(tile: Tile, startBit: Short, numBits: Short): Tile = {
81-
// this is the last `numBits` positions of "111111111111111"
82-
val widthMask = Short.MaxValue >> (15 - numBits)
83-
// map preserving the nodata structure
84-
tile.mapIfSet(x x >> startBit & widthMask)
85-
}
80+
protected def op(tile: Tile, startBit: Int, numBits: Int): Tile = ExtractBits(tile, startBit, numBits)
8681

8782
}
8883

8984
object ExtractBits{
9085
def apply(tile: Column, startBit: Column, numBits: Column): Column =
9186
new Column(ExtractBits(tile.expr, startBit.expr, numBits.expr))
9287

93-
}
88+
def apply(tile: Tile, startBit: Int, numBits: Int): Tile = {
89+
// this is the last `numBits` positions of "111111111111111"
90+
val widthMask = Int.MaxValue >> (63 - numBits)
91+
// map preserving the nodata structure
92+
tile.mapIfSet(x x >> startBit & widthMask)
93+
}
9494

95+
}

docs/src/main/paradox/reference.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,23 +167,20 @@ Tile rf_make_ones_tile(Int tile_columns, Int tile_rows, [CellType cell_type])
167167
Tile rf_make_ones_tile(Int tile_columns, Int tile_rows, [String cell_type_name])
168168
```
169169

170-
171170
Create a `tile` of shape `tile_columns` by `tile_rows` full of ones, with the optional cell type; default is float64. See @ref:[this discussion](nodata-handling.md#cell-types) on cell types for info on the `cell_type` argument. All arguments are literal values and not column expressions.
172171

173172
### rf_make_constant_tile
174173

175174
Tile rf_make_constant_tile(Numeric constant, Int tile_columns, Int tile_rows, [CellType cell_type])
176175
Tile rf_make_constant_tile(Numeric constant, Int tile_columns, Int tile_rows, [String cell_type_name])
177176

178-
179177
Create a `tile` of shape `tile_columns` by `tile_rows` full of `constant`, with the optional cell type; default is float64. See @ref:[this discussion](nodata-handling.md#cell-types) on cell types for info on the `cell_type` argument. All arguments are literal values and not column expressions.
180178

181179

182180
### rf_rasterize
183181

184182
Tile rf_rasterize(Geometry geom, Geometry tile_bounds, Int value, Int tile_columns, Int tile_rows)
185183

186-
187184
Convert a vector Geometry `geom` into a Tile representation. The `value` will be "burned-in" to the returned `tile` where the `geom` intersects the `tile_bounds`. Returned `tile` will have shape `tile_columns` by `tile_rows`. Values outside the `geom` will be assigned a NoData value. Returned `tile` has cell type `int32`, note that `value` is of type Int.
188185

189186
Parameters `tile_columns` and `tile_rows` are literals, not column expressions. The others are column expressions.
@@ -236,10 +233,35 @@ Generate a `tile` with the values from `data_tile`, with NoData in cells where t
236233
### rf_mask_by_values
237234

238235
Tile rf_mask_by_values(Tile data_tile, Tile mask_tile, Array mask_values)
239-
Tile rf_mask_by_values(Tile data_tile, Tile mask_tile, seq mask_values)
236+
Tile rf_mask_by_values(Tile data_tile, Tile mask_tile, list mask_values)
240237

241238
Generate a `tile` with the values from `data_tile`, with NoData in cells where the `mask_tile` is in the `mask_values` Array or list. `mask_values` can be a [`pyspark.sql.ArrayType`][Array] or a `list`.
242239

240+
### rf_mask_by_bit
241+
242+
Tile rf_mask_by_bits(Tile tile, Tile mask_tile, Int bit_position, Bool mask_value)
243+
244+
Applies a mask using bit values in the `mask_tile`. Working from the right, the bit at `bit_position` is @ref:[extracted](reference.md#rf_local_extract_bits) from cell values of the `mask_tile`. In all locations where these are equal to the `mask_value`, the returned tile is set to NoData; otherwise the original `tile` cell value is returned.
245+
246+
This is a single-bit version of @ref:[`rf_mask_by_bits`](reference.md#rf-mask-by-bits).
247+
248+
### rf_mask_by_bits
249+
250+
Tile rf_mask_by_bits(Tile tile, Tile mask_tile, Int start_bit, Int num_bits, Array mask_values)
251+
Tile rf_mask_by_bits(Tile tile, Tile mask_tile, Int start_bit, Int num_bits, list mask_values)
252+
253+
Applies a mask from blacklisted bit values in the `mask_tile`. Working from the right, the bits from `start_bit` to `start_bit + num_bits` are @ref:[extracted](reference.md#rf_local_extract_bits) from cell values of the `mask_tile`. In all locations where these are in the `mask_values`, the returned tile is set to NoData; otherwise the original `tile` cell value is returned.
254+
255+
This function is not available in the SQL API. The below is equivalent:
256+
257+
```sql
258+
SELECT rf_mask_by_values(
259+
tile,
260+
rf_extract_bits(mask_tile, start_bit, num_bits),
261+
mask_values
262+
),
263+
```
264+
243265
### rf_inverse_mask
244266

245267
Tile rf_inverse_mask(Tile tile, Tile mask)
@@ -406,6 +428,15 @@ Returns a `tile` column containing the element-wise inequality of `tile1` and `r
406428

407429
Returns a `tile` column with cell values of 1 where the `tile` cell value is in the provided array or list. The `array` is a Spark SQL [Array][Array]. A python `list` of numeric values can also be passed.
408430

431+
### rf_local_extract_bits
432+
433+
Tile rf_local_extract_bits(Tile tile, Int start_bit, Int num_bits)
434+
Tile rf_local_extract_bits(Tile tile, Int start_bit)
435+
436+
Extract value from specified bits of the cells' underlying binary data. Working from the right, the bits from `start_bit` to `start_bit + num_bits` are extracted from cell values of the `tile`. The `start_bit` is zero indexed. If `num_bits` is not provided, a single bit is extracted.
437+
438+
A common use case for this function is covered by @ref:[`rf_mask_by_bits`](reference.md#rf-mask-by-bits).
439+
409440
### rf_round
410441

411442
Tile rf_round(Tile tile)

docs/src/main/paradox/release-notes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 0.8.x
44

5+
### 0.8.5
6+
7+
* Add `rf_mask_by_bit`, `rf_mask_by_bits` and `rf_local_extract_bits` to deal with bit packed quality masks. Updated the masking documentation to demonstrate the use of these functions.
8+
59
### 0.8.4
610

711
* Upgraded to Spark 2.4.4

0 commit comments

Comments
 (0)