I have a vector data set of address points and a raster layer showing flood inundation
Not all address points are within the flood extent but if I use is_exposed on these 2 layers it returns True for all address points.
pipeline_test.txt
input(relation: 'Address_Points_Clipped', name: 'exposure') as exposures_input
-> select({*, is_exposed(exposure.geom, bookmark('max_extent_clipped'))}) as hazard_layer
-> save('hazard_ouptut.csv', format:'csv')
[Address_Points_Clipped]
location = Data\Exposure\clipped-addresses.csv
set-attribute.geom = create_point("gd2000_ycoord","gd2000_xcoord")
crs-name = EPSG:4326
[max_extent_clipped]
location = Data\Hazard\NZ_ARI1000_200-clipped.tif
format = geotiff
crs-name = EPSG:2193
I was expecting that address points that fell within the “No Data” areas of NZ_ARI1000_200-clipped.tif would be assigned a 0/False in the is_exposed column.
Hi John,
The problem is this line in your pipeline:
You’re passing the bookmark/coverage directly to is_exposed()
, whereas it expects to get the hazard intensity value sampled from the coverage. i.e. you want something more like this:
-> select({*, is_exposed(exposure.geom, sample_one(exposure, bookmark('max_extent_clipped')))})
It might be slightly clearer to split this over 2 steps (which also lets you see the hazard intensity value that was sampled).
-> select({*, sample_one(exposure.geom, bookmark('max_extent_clipped')) as hazard})
-> select({*, is_exposed(exposure.geom, hazard)})
A few more follow-up notes:
is_exposed()
returns 1 if the hazard
argument is present (i.e. not null) and 0 if not. It’s basically the same behaviour as:
if_then_else(is_null(hazard), 0, 1) as is_exposed
is_exposed()
relies on the sampling operation returning null if the hazard does not intersect the element-at-risk. Some GeoTIFF coverages may return zero instead of null for the unexposed regions, in which case you’d want a custom function that is more like:
if_then_else(hazard > 0, 1, 0) as is_exposed
One final gotcha when writing a pipeline manually from scratch is do not pass the return value from sample()
directly to is_exposed()
. sample()
returns a list of hazard intensities, and so the list will always be non-null (using the wizard to build your pipeline will avoid this pitfall). Instead, you can used sample_one()
or sample_centroid()
, or do something like this:
if_then_else(length(hazard) > 0, 1, 0) as is_exposed
Cheers Tim, this is working now. I ended up just using sample_one and then filtering based on whether or not the hazard column is empty
-> select({*, sample_one(exposure.geom, bookmark('max_extent')) as hazard})
-> filter("hazard" != '')
OK, that will work, but the reasons why it works are a bit convoluted. That check is essentially the same as:
riskscape expr eval " '' != null_of('floating') "
<nothing>
So although you are comparing a text string and a number there, because one is null the overall result is also null (or <nothing>
). In the filter()
step, null/nothing gets treated as false, so those unexposed buildings get removed.
It’s probably slightly nicer to explicitly check against null in the filter step, e.g.
filter(is_not_null(hazard))
1 Like