# 
# RiskScape™ Copyright New Zealand Institute for Earth Science Limited
# (Earth Sciences New Zealand) is distributed for research purposes only
# under the terms of AGPLv3.
# 
# RiskScape™ Copyright 2026 New Zealand Institute for Earth Science
# Limited (Earth Sciences New Zealand). All rights reserved. Source code
# available under the AGPLv3.
# 
# This program is free software: you can redistribute it and/or modify it under
#  the terms of the GNU Affero General Public License as published by the Free
#  Software Foundation, either version 3 of the License, or (at your option) any
#  later version.
# 
# This program is distributed for RESEARCH PURPOSES ONLY, in the hope that it will
# be useful for research and education initiatives.
# 
# If you are not a researcher, or you are a researcher who wishes to use this
# program on terms other than AGPLv3 (including those who wish to restrict the
# distribution of any source code created using this program), please contact:
# https://riskscape.org.nz
# 
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Affero General Public License for more details.  You should have received a copy
# of the GNU Affero General Public License along with this program.  If not, see
# <http://www.gnu.org/licenses/>.
# 
# By way of summary only, under the AGPLv3:
#     • Permissions of this strongest copyleft license are conditioned
#       on making available complete source code of licensed works and
#       modifications, which include larger works using a licensed work,
#       under the same license.
#     • Copyright and license notices must be preserved.
#     • Contributors provide an express grant of patent rights.
#     • When a modified version is used to provide a service over a
#       network, the complete source code of the modified version must be made
#       available.
# 

# Secrets

nz.org.riskscape.defaults.auth.PlatformSecret.description = \
  Use a WebDAV Token for accessing files stored in the RiskScape Platform.

nz.org.riskscape.defaults.auth.PlatformSecret.params.hostname = \
  The `hostname` of the remote server that this secret applies to, i.e. this secret is used for authenticating \
  with this server.

nz.org.riskscape.defaults.auth.PlatformSecret.params.token = \
  Your RiskScape Platform `WebDAV` token.  Get one from from https://riskscape.nz/user/profile.

nz.org.riskscape.defaults.auth.KoordinatesSecret.description = \
  Use a Koordinates API key for accessing data services, such as LINZ WFS data.

nz.org.riskscape.defaults.auth.KoordinatesSecret.params.api-key = \
  Your API key, generated by a Koordinated-based website

## Bookmark formats/options

# CsvResolver
nz.org.riskscape.engine.defaults.data.CsvResolver.params.geometry-attribute = \
  Give a name to the geometry attribute, will default to `the_geom` if `geometry-expression` is given.

nz.org.riskscape.engine.defaults.data.CsvResolver.params.geometry-expression = \
  An ECQL expression that creates geometry from the source data.  For example, `createPoint(long, lat)` \
  would build a point from source columns named long and lat.  This option is applied before \
  map-attribute, CRS and type are applied.

nz.org.riskscape.engine.defaults.data.CsvResolver.params.add-line-numbers = \
  Set to true to include a `__linenum` meta attribute with data from this relation.  Useful for debugging \
  data quality issues

nz.org.riskscape.engine.defaults.data.CsvResolver.params.type-detection = \
  When true type detection will scan the CSV data to detect the best type. \n\
  Columns that only contain numeric values will be made `floating`. \n\
  If `lat`/`lon` columns are found (with numeric values) then a point attribute named `geometry` will be added \
  unless there is already an attribute with that name or an attribute with a geometry type already exists. \n\
  Note: \n\
  - type detection is applied after any `geometry-attribute`/`geometry-expression`/`map-attribute` mappings \n\
  - is not compatible with the `type` option. \n\
  Type detection may be slow for large CSV data files. Manually mapping types and ensuring type detection is off \
  will improve performance in most cases. \n\
  Defaults to true unless a type has been set.

nz.org.riskscape.engine.defaults.data.jdbc.GeoPackageFormat.description = \
  Writes spatial data to a GeoPackage output file.

nz.org.riskscape.engine.defaults.data.MosaicCoverageResolver.description = \
  Combines multiple other coverages in to a virtual mosaic coverage.  This is a beta feature and has a number of \
  restrictions with its use.  The location should point to a plain text "mosaic" file that is itself a list of \
  locations (relative to the mosiac) that are sampled when the mosaic is sampled.  This allows a large set of \
  individual rasters, often GeoTIFF files, to be presented to a RiskScape model as though they are one coherent raster.

# ShapefileBookmarkResolver
nz.org.riskscape.engine.defaults.data.ShapefileBookmarkResolver.params.crs-longitude-first = \
  Set this to true to force a CRS that has been assigned via the `crs-name` parameter to have a LONG, LAT \
  axis order. Longitude first is the default for Shapefiles as the format itself specifies this axis order. \
  So it should not be necessary for this option to be used with valid Shapefiles. However if you have a \
  shapefile that has coordinates in with a LAT, LONG axis order you can set `crs-longitude-first` to \
  false to have the CRS defined axis order used. \
  See http://docs.geotools.org/latest/userguide/library/referencing/order.html for more information.

# WfsBookmarkResolver
nz.org.riskscape.engine.defaults.data.WfsBookmarkResolver.params.wfs-page-size = \
  When the WFS 2.0 server supports paging, the 'page-size' specifies how many features RiskScape will ask for in each WFS request. \
  If the WFS server advertises a `CountDefault` WFS constraint (sometimes called `maxRecordCount` on the server), \
  then RiskScape will use that count, unless the specified `wfs-page-size` is smaller. \
  Sending too many features in single WFS response may result in server timeout errors, which lowering the `wfs-page-size` might fix. \
  If the WFS server has a record limit that RiskScape cannot detect, then you will need to specify `wfs-page-size` for the bookmark

#
## Models
#

nz.org.riskscape.engine.defaults.TablePipelineModel.description = \
  Performs analysis on a single data source without joins. \
  Use the model's parameters to designate the assets and hazards \
  from the set of attributes that the file includes


nz.org.riskscape.engine.defaults.TablePipelineModel.params.relation = \
  The source of data, aka the table, for the model

nz.org.riskscape.engine.defaults.TablePipelineModel.params.include-asset-in-output = \
  Include asset attributes in the model's output

nz.org.riskscape.engine.defaults.TablePipelineModel.params.include-hazard-in-output = \
  Include matched hazard value in output

nz.org.riskscape.engine.defaults.TablePipelineModel.params.skip-invalid-rows = \
  Set this to true to skip invalid rows from the source data, rather than failing

nz.org.riskscape.engine.defaults.TablePipelineModel.params.allow-missing-attributes = \
  Set this to true to allow rows in the source data to having missing attributes

#
# Function descriptions
#
nz.org.riskscape.engine.function.IdentifiedFunction.by-id.aal_trapz.description = \
  Aggregate function for calculating an Average Annual Loss (AAL) \
  for hazard-based probabilistic data using trapezoid integration

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.aal_trapz.description.1 = \
  Aggregates a series of event loss data-points to calculate the AAL. \
  The event loss data points are plotted as piecewise linear x,y coordinates, \
  where x is the exceedance probability (EP) and y is the loss. \
  The AAL is then the area under the loss/EP curve, which is determined using trapezoid integration.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.aal_trapz.description.2 = \
  This function produces a similar result to `numpy.trapz(x=[0.0]+EPs, y=[max(losses)]+losses)`. \
  The extra EP=0.0 data-point represents the area under the loss/EP curve beyond the \
  maximum known loss (these losses can be inferred to be greater than or equal to the max loss).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.aal_trapz.description.3 = \
  Note that any null loss values are treated as zero. \
  Probability values must fall between 0.0 and 1.0 and cannot be duplicated.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.aal_trapz.description.4 = \
  This function can also be used outside of aggregate 'group' steps by passing it the \
  losses and exceedance probabilities as lists. This approach is more memory-efficient when \
  calculating a large number of AAL calculations, such as a per-property AAL.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.apply_continuous.description = \
  Apply an x-value to a pre-computed curve using interpolation.  Used alongside `create_continuous` to \
  perform large probabilistic analysis with a computationally expensive loss function.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bookmark.description = \
  Lookup data from a project by its bookmark id, with an optional second `options` argument that allows you to modify \
  the options set in the original bookmark.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bookmark.description.1 = \
  The first argument to bookmark does not have to be an existing bookmark id, it could be a file path or URI.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bookmark.description.2 = \
  The `options` argument can be used to override/set the options in the bookmark. \
  Example: `bookmark('buildings', {location: 'data/all_buildings.csv', format: 'csv', add_line_numbers: true})` - \
  looks up a bookmark with the id 'buildings', changes the location, sets the format to `csv`, and enables line numbers.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bookmark.description.3 = \
  The `type` argument is used to set the type that is expected to be returned. This is required when either \
  the `id` or `options` are not constants. \
  Example: `bookmark(xyz, options: {}, type: 'coverage(floating)')` where `zyz` is a property expected \
  to contain the path to a grid coverage. Note that if the returned bookmark does not contain the \
  expected data type then your pipeline will fail mid execution.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bounds.description = \
  Returns a polygon containing the spatial bounds (extent) of the given relation or coverage.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bounds.description.1 = \
  If the argument is a constant string it is treated as a bookmark ID or filepath. This means that \
  `bounds('my-hazard')` and `bounds(bookmark('my-hazard'))` will both return the same result.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bounds.description.2 = \
  The returned bounds may be used with other geometry functions,  e.g `intersects(exposure, bounds('my-hazard'))` \
  would return true for each exposure that has some intersection with the `my-hazard` layer's spatial extent.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bounds.description.3 = \
  The spatial bounds is a rectangular box that is the smallest size to cover all of the geometries. \
  For further information see https://en.wikipedia.org/wiki/Minimum_bounding_box

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description = \
  Aggregate function that assigns a row of data to one or more categories, or 'buckets', and aggregates each bucket \
  individually.  This is conceptually similar to a `SUMIF` spreadsheet operation, but is more powerful and flexible as \
  any aggregate operation can be used, and multiple categories can be aggregated at once.  See `bucket_range()`\
  for a slightly simpler function that aggregates based on what range a value falls into.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.1 = \
  The bucket() function requires three arguments: the `buckets` or categories you are interested in, \
  a `pick` lambda expression which determines which bucket(s) apply for any given row, \
  and a `select` aggregate expression that defines how to aggregate the data.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.2 = \
  For example, say you are aggregating an event loss table by region, and you want to see the regional damage summarized by building type. \
  Such an expression might look like this, where each bucket represents a building type: \
  bucket(pick: bucket -> building.type = bucket, select: {sum(loss) as total_loss, count(*)}, buckets: ['concrete', 'steel', 'brick'])

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.3 = \
  The result returned is a struct consisting of the `select` aggregate expression applied to each bucket separately.  E.g. \
  `{concrete.total_loss, concrete.count, steel.total_loss, steel.count, brick.total_loss, brick.count}`.  Note that \
  the name of each bucket is used in the result struct.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.4 = \
  The `pick` argument is used to compare rows against all of the buckets.  If a bucket applies to the row, then the \
  expression must return `true`.  If many buckets apply, then each matching bucket will accumulate rows. If the row \
  does not match any bucket, then that data is simply ignored.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.5 = \
  The `select` argument gives the aggregate expression to apply to rows in each of the buckets, for example \
  `sum(loss)` or `percentile(loss, 50)`.  These expressions can be complex, e.g. `{'$' + str(sum(loss)) as \
  "Total Losses (NZD)"}`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.6 = \
  The `buckets` argument is used to define the set of buckets used to group rows in the aggregation. \
  The simplest approach is to specify a list, in which case there will be a bucket for each list item, \
  and each bucket will have the same name and value. Alternatively, the `buckets` argument can be specified \
  as a struct (e.g `buckets: {Concrete: 'concrete', Steel: 'steel', Brick: 'brick'}`). \
  This can be useful if you do not want the bucket's name to match the value. A bucket can be \
  simple like a numeric value or a bit of text, or can be a more complex set of criteria.  Note that every bucket \
  must be of the exact same type, including nullability.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket.description.7 = \
  The `buckets` argument can also be specified as a `set` or `enum` type (e.g `buckets: 'my_set_type'`). \
  In this case a bucket will be created for each item in the given `set` or `enum`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description = \
  Aggregate function that assigns each row of data to a 'bucket' based on the numeric range a given value falls into, \
  and then aggregates each bucket separately.  This works the same as the `bucket()` function, but is a bit simpler \
  to use when dealing with numeric ranges.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.1 = \
  The bucket_range() function requires three arguments: the numeric `range` you are interested in, \
  the attribute in each row to `pick` (i.e. what to match against the ranges), \
  and a `select` aggregate expression that defines how to aggregate the data.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.2 = \
  For example, an event loss table could by bucketed by loss range and have a count and sum of losses between \
  predefined levels.  Such an expression might look like this: `bucket_range(pick: loss, select: {sum(loss) as total_loss, \
  count(*)}, range: [1, 5000, 100000])`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.3 = \
  The result returned is a struct consisting of the `select` aggregate expression applied to each bucket separately.  E.g. \
  `{range_<_1.total_loss, range_<_1.count, range_1_5000.total_loss, range_1_5000.count, range_5000_100000.total_loss, range_5000_100000.count, range_100000_+.total_loss, range_100000_+.count}`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.4 = \
  The `select` argument gives the aggregate expression to apply to rows in each of the buckets, for example \
  `sum(loss)` or `percentile(loss, 50)`.  These expressions can be complex, e.g. `{'$' + str(sum(loss)) as \
  "Total Losses (NZD)"}`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.5 = \
  The `pick` argument specifies the value in each row to compare against the `range` buckets.  A match is \
  found if `pick` is `>=` the bucket's lower-bound and `<` its upper-bound, e.g. the comparison for bucket `range_1_10` would be `pick >= 1 and pick < 10`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.bucket_range.description.6 = \
  The `range` argument is a numeric list, where each list element defines a boundary for a bucket. For example, the list `[1, 2]` would \
  yield the following buckets: `range_<_1`, `range_1_2` and `range_2_+`. \
  The `range_<_1` and `range_2_+` bounds get added automatically to ensure that any values \
  that might fall outside the specified range do not get ignored. \
  To avoid this default behaviour and deliberately ignore values, \
  you can pass in a 4th argument `options: { add_bounds: false })`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.call.description = \
  Utility function for calling a function using its name (as text), which allows function calls to be parameterized.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.call.description.1 = \
  For example `call('my_loss_function', {exposure, hazard})` is the same as `my_loss_function(exposure, hazard)`. \
  This can be parameterized to allow users of the model to swap in a custom function without having to change the model \
  pipeline, e.g `call($loss_function, {exposure, hazard})`. See the pipeline-parameters section in the documentation for \
  more details.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.call.description.2 = \
  Note that the only order of the attributes in the arguments struct determines how they will be passed to the target \
  function. Any keyword arguments in the target function will be ignored.  It does not matter what you name the \
  attributes in the arguments struct, only the attribute order will be used.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.call.description.3 = \
  The message option may be used to customize the error message users will be given if the given function \
  is not compatible with the given arguments. For example \
  `call('my_loss_function', {exposure, hazard}, options: {message: 'requires exposure of the building type, and floating hazard'})`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description = \
  Combines multiple coverages into one. This lets you sample multiple hazard or resource-layers with a single \
  operation.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.1 = \
  For example, `combine_coverages({shaking: event.shakemap, soil_type: resource_layer}, 100)` would build a new \
  coverage.  Sampling the new coverage would return a struct. The attributes in this struct are the \
  combined result of sampling the `event.shakemap` and `resource_layer` coverages respectively. \
  The attributes names will be `shaking` and `soil_type` (or derivatives of these).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.2 = \
  The first argument, `coverages`, must be a `{ key: value, ... }` struct expression. \
  Each `value` in this struct expression must be a coverage. \
  Each `key` will be used for the attribute names in the result, when the combined coverage is sampled. \
  If the individual coverage is raster data, the key name will be used exactly, e.g. `shaking`. \
  If the individual coverage is vector data, the key name will be used as a prefix, e.g. `shaking_pga`. \
  Note that the underlying vector-layer geometry is not returned at all.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.3 = \
  The second `grid-resolution` argument specifies a common grid-size, in metres, to use across all the coverages. \
  When the combined coverage is sampled using non-point geometry, the input geometry will be cut up using the given \
  `grid-resolution` distance.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.4 = \
  Cutting is done using the same method as the `segment_by_grid()` function. The `grid-resolution` should generally \
  match the raster coverage with the smallest grid size.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.5 = \
  Note that sampling intersections from a combined coverage only uses the centre point of each grid segment. \
  Sampling may produce slightly different results at different grid-resolutions, especially when sampling a \
  combined vector layer, and especially if the vector geometry is small, such as ballistics data.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.combine_coverages.description.6 = \
  Using a smaller `grid-resolution` will provide better accuracy when sampling vector data. \
  However, a smaller `grid-resolution` will be much more processing intensive and make your model run slower.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous.description = \
  Creates a 'continuous curve' that will more efficiently evaluate a computationally expensive \
  loss function for probabilistic modelling.  Pass the curve result to `apply_continuous()` \
  where you would normally call your loss function, e.g. `apply_continuous(curve, hazard_value)`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous.description.1 = \
  This is useful when there are a large number of hazard intensity values to process, \
  and they all fall into a similar range of values.  Instead of executing the loss function \
  for every single hazard intensity value, the function is executed at most once for each of the `x-values`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous.description.2 = \
  For example, `create_continuous([0.1, 0.2, 0.3], x -> my_loss_function(\
  exposure, x)` will only execute `my_loss_function` at most three times, once each for 0.1, 0.2, 0.3.  \
  Any hazard intensities that fall between 0.1 and 0.3 will be interpolated based on the function's return values.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous.description.3 = \
  Be careful that the `x-values` you specify accurately reflect the range of hazard intensities you expect.  \
  The min or max x-values will be used if the hazard intensity falls outside this range.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description = \
  Creates a 'continuous curve' that will more efficiently evaluate a computationally expensive \
  loss function for probabilistic modelling.  Pass the curve result to `apply_continuous()` \
  where you would normally call your loss function, e.g. `apply_continuous(curve, hv1, hv2)`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description.1 = \
  This is useful when there are a large number of hazard intensity values to process, \
  and they all fall into a similar range of values.  Instead of executing the loss function \
  for every single hazard intensity value, the function is executed at most once for each \
  combination of the `x-values` and `y-values`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description.2 = \
  For example, `create_continuous_2d([0.1, 0.2, 0.3], [0.1, 0.2, 0.3], (x, y) -> my_loss_function(\
  exposure, x, y)` will only execute `my_loss_function` at most nine times, once for each combination \
  of x and y values. \
  Any hazard intensities that fall between 0.1 and 0.3 will be interpolated between the known values \
  using bilinear interpolation.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description.3 = \
  Be careful that the `x-values` and `y-values` you specify accurately reflect the range of hazard intensities you expect.  \
  The min or max value will be used if the hazard intensity falls outside this range.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description.4 = \
  The `zero_loss` option is a potential performance improvement when calling a Python damage or loss \
  function a large number of times. When a zero loss is returned for a given x and y value, RiskScape \
  can then bypass the Python function and assume that any lower x or y values will also result in a \
  zero loss. For example, say x=0.3 (PGA) and y=7 (magnitude) results in a zero loss, then x=0.2 or \
  y=6 will also result in a zero loss, without needing the slower Python function call. \
  This assumes your loss function is monotonically increasing with respect to x and y. \
  To use this option, you need to specify the zero-loss return value as an expression, e.g. \
  `options: { zero_loss: { totalLoss: 0.0, DR: 0.0 } }`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.create_continuous_2d.description.5 = \
  The advanced `compress` option enables a potential memory usage optimization. \
  Using `compress` will store known data points in a single array of 32 bit floating point values, \
  rather than storing individual tuples (or boxed types).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.ends_with.description = \
  Returns true if the given `test` string argument ends with the `suffix` argument. False otherwise

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.fit_curve.description = \
  Aggregate function for fitting a mathematical curve to a set of two dimensional data points (i.e. X, Y values). \
  This function attempts to fit a curve to these points, picking the best-scoring curve from all curve types that have \
  been registered.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.fit_curve.description.1 = \
  The return value contains the details of the best-fitting curve, which includes: \
  the curve 'function', the 'fit' ID (i.e. `continuous`, `linear`, `powerlaw`, etc), and the \
  r² 'score' for this curve against the original data points. Passing the returned function \
  to the `apply` function will sample the curve, i.e. determine the Y value for a given X value.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.fit_curve.description.2 = \
  For example, use the expression `fit_curve(x-value: loss, y-value: probability) as loss_curve` \
  to fit a curve to a set of probabilistic losses. You can then use `apply(loss_curve.function, threshold)` \
  to determine the probability (Y value) of the given `threshold` loss (X value) being reached.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.fit_curve.description.3 = \
  The optional 'fitters' argument describes specific curves(s) that should be used. \
  For example, using `fit_curve(loss, probability, fitters: {'continuous'})` would only \
  attempt to fit a continuous curve to the given data points. The default is to attempt \
  to fit all possible curves.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.fit_curve.description.4 = \
  Note that when selecting from multiple curves (the default), you can refer to the \
  'fit' ID in the return value to verify the best-fit that was actually chosen.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.if.description = \
  A function that fills a similar role to an `if` statement in other programming languages, \
  e.g. `if(depth > 1, then: 'damaged', else: 'safe')`. Either the `then` or the `else` argument \
  is returned, depending on whether the `condition` expression evaluates to true or false.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.if.description.1 = \
  In general, the return-type will be common to both the `then` and `else` expressions, \
  or the 'anything' type will be used if there is no common type. \
  If the `condition` argument is a 'constant' expression (i.e. always true or false), \
  then either the `then` or `else` expression will always be used, and the return-type will match that.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.if.description.2 = \
  The `else` argument is optional. For example `if(false, 'foo')` will return null and the return type \
  will be a nullable version of the `then` argument's type.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.if.description.3 = \
  RiskScape functions evaluate their arguments before the function is called, which can be wasteful when an \
  expression takes a while to run, e.g. a spatial lookup. To avoid this behaviour, the `then` and `else` arguments \
  can be supplied as lambda expressions. These are only evaluated when the particular case applies. In the \
  example of `if(exposure.high_lsl_risk, () -> sample_intersections(exposure, landslide_susceptibility), else: 0)` the `sample_intersections` \
  function will only be called if the `high_lsl_risk` attribute is true, avoiding unnecessary computation.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.if_then_else.description = \
  Deprecated, `if_then_else` is the same as `if`. See `if` for function help.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.layer_intersection.description = \
  Compute the intersection of a feature (a geometry-containing struct) with all of the features in another layer.  The \
  function returns a list of features that represent the intersection.  If the function is given just two arguments, \
  then the returned features are a copy of the original feature with just the geometry replaced by the \
  intersection.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.layer_intersection.description.1 = \
  The third optional argument is a struct containing `layer` attributes to merge into the result. \
  The identifier of each struct member is the new name the attribute will be given in the result. \
  For example, if the given argument was `{area_name: 'name', soil_type: soil_type}` then this would merge in the \
  `soil_type` attribute from the given `layer`, but rename the `name` attribute as `area_name` in the result.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.layer_intersection.description.2 = \
  The fourth optional `return_difference` argument determines what parts of the original geometry are included in the result. \
  If `false` (the default), then only the geometry intersection is returned. \
  If `true`, the intersection as well as any difference (non-overlapping geometry) is returned.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.lazy_lookup.description = \
  Produces a lookup table that will accept the given `key-type` and use the `mapping-function` to derive \
  the lookup value. The `mapping-function` is only called for key values that are requested and these \
  values are cached in the lookup table should they be required again.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.lazy_lookup.description.1 = \
  For example `lazy_lookup('integer', key -> expensive_function(key))` will create a lookup table that is \
  backed by the `expensive_function`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.lazy_lookup.description.2 = \
  Note that nullable types are not allowed for the `key-type` or the `mapping-function` return type.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.lazy_lookup.description.3 = \
  The lazy_lookup function supports some advanced options for tuning caching behaviour: \n\
  - `maximum_size` - limits how many entries can be stored in the cache. If exceeded, least recently used \
  items are removed first. \n\
  - `initial_capacity` - a size for the cache when created.  Setting it high will prevent expensive resizing \
  operations during a model run, but setting it too high can waste memory.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description = \
  Turns a list of items into column-wise data (i.e. a struct type). \
  This can be helpful when saving a list to file. For example, a list \
  containing 3 items could be turned into 3 separate columns in the \
  output CSV file.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.1 = \
  Each item in the given list becomes a "column" (i.e. an attribute or \
  struct member) in the return value. The column names can either be \
  explicitly specified or auto-generated based on the item's order in the list.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.2 = \
  An example of explicitly specifying the column names would be: \
  `list_to_columns([1, 2], columns: { names: ['one', 'two']})` which would \
  return `{one=1, two=2}`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.3 = \
  Alternatively, the column names can be based on the item's position in \
  the list, e.g. the first list item gets named column '1'. In this case, \
  you need to specify the total number of columns (i.e. items in the \
  list). E.g `list_to_columns([3, 4], columns: { number: 2})` will return \
  `{1=3, 2=4}`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.4 = \
  Note that if the list contains more items than the specified 'number' \
  or 'names', then the extraneous list items will be discarded.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.5 = \
  For convenience, a prefix can also be given to the columns names. E.g \
  `list_to_columns([5, 6], columns: { number: 2, prefix: 'value'})` will \
  return `{value1=5, value2=6}`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.6 = \
  You can also change how the numbering starts. For example, if \
  you prefer zero-based numbering, then `list_to_columns([7, 8], columns: { number: 2, start_numbering: 0 })` \
  will return `{0=7, 1=8}`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_columns.description.7 = \
  By default the output columns will have a nullable type wrapping added. This is because when \
  the function is called there may not be enough list items to populate all of the columns. \
  The nullable wrapping can be removed by setting the `nullable` option to false. \
  Note that when nullable is set to false an evaluation error will be thrown if there are not \
  enough list items to fill all the columns.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_tuple.description = \
  Returns a tuple containing an attribute for each item in the given list, until the `upto` limit \
  is reached. This function has been deprecated. Please use `list_to_columns` instead.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.list_to_tuple.description.1 = \
  The member names are formed from the `prefix` (defaults to empty string) and the list position. \
  E.g the expression `list_to_tuple(list, 2, 'prefix')` will return the tuple \
  `{prefix0: item0, prefix1: item1}`. If the given list does not contain enough items to fill \
  the tuple then the missing attributes will have a null value.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.lookup.description = \
  Lookup data from a lookup table by key, returning null if no value matched.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map.description = \
  Apply an expression to each element in a list to produce a new list.  \
  Serves the same purpose in RiskScape as a for loop or a list comprehension.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map.description.1 = \
  For convenience, the `iterable` argument does not have to be a list type.  \
  You can pass `map()` a single item and the `foreach` lambda expression will be applied to \
  the first argument directly.  E.g. `map(1, foreach: (x) -> x + 1)` will simply return 2.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map.description.2 = \
  Treating both lists and single items as `iterable` makes pipeline code reusable for a \
  variety of different modelling situations.  For example, sampling the hazard-layer can \
  result in either a single hazard intensity value or a list of values, depending on the function used.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map_coverage.description = \
  Applies an expression to transform the value(s) sampled from the given coverage. \
  For example, this lets you convert the sampled value(s) from centimetres to metres, \
  or from log-scale units to non-log units.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map_coverage.description.1 = \
  For example, to convert from centimetres to metres you would use: `map_coverage(coverage, (x) -> x / 100)`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.map_coverage.description.2 = \
  Note that returning null from the expression will map the result to `NO_DATA`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.normalize_geometry.description = \
  Renames the geometry attribute so that it has the specified name.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.normalize_geometry.description.1 = \
  This ensures that tuples contain only one geometry attribute with a specific name, e.g \
  `select({*, normalize_geometry(exposure, 'geom') as exposure})` would replace any geometry \
  attribute(s) in the 'exposure' tuple with a single `geom` attribute.  Useful for dealing with the different \
  conventions spatial file formats use for naming geometry attribute, so that a pipeline \
  can be more easily re-used without modification.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.normalize_geometry.description.2 = \
  If no geometry attribute is found, then an error will be produced and the model will refuse to run. \
  An optional `message` can be specified to customize the error message displayed in this case.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.normalize_geometry.description.3 = \
  If the specified attribute name already exists, and is not a geometry type, then the function will fail to \
  validate. This avoids overwriting non-geometry data accidentally.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.relation_to_coverage.description = \
  DEPRECATED please use `to_coverage` instead. \
  Makes a relation into a coverage (Only possible for relations that include a geometry attribute).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.relation_to_coverage.description.1 = \
  Converts a relation in to a coverage, allowing it to be sampled using one of the sampling functions (e.g. `sample_intersections`, \
  `sample_centroid` or `sample_closest`).  The coverage is constructed by adding all of the relation's tuples in to a \
  spatial index (The relation must have a single geometry member) which is queried for matching tuples when sampled.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.relation_to_coverage.description.2 = \
  There are two types of index that can be constructed, 'intersection' and 'nearest_neighbour, which can be \
  chosen by specifying the `index` option, e.g. `relation_to_coverage(relation, options: {index: 'intersection'})`. \
  The default `index` is `'intersection'`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.relation_to_coverage.description.3 = \
  The `intersection` index is most appropriate for indexing polygonal features. The sampling \
  operation will query the index for any intersecting features, and return those that match according to the \
  semantics of the sampling operation that was used. The `intersection` index is the default index type.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.relation_to_coverage.description.4 = \
  The `nearest_neighbour` index is best when indexing point features.  A sampling operation will query \
  the index for the nearest feature's point (with a max distance cut off).  Only `sample_centroid` is currently \
  supported for this type of index.  The distance cutoff must be supplied as the `nearest_neighbour_max_distance` \
  option. E.g to use a nearest neighbour index with a cutoff of one kilometre use \
  `relation_to_coverage(relation, options:  {index: 'nearest_neighbour', nearest_neighbour_max_distance: 1000})`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample.description = \
  Deprecated: `sample` is an alias to `sample_intersections`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_intersections.description = \
  Selects all the values and intersecting geometries from a coverage that intersect with the given geometry.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_intersections.description.1 = \
  This function is useful for determining details such as the total amount that a polygon or line-string \
  is exposed to a hazard, or the specific min/mean/max/etc hazard intensity measure for a given feature.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_intersections.description.2 = \
  The given geometry may intersect the coverage multiple times (e.g. multiple pixels in a GeoTIFF), \
  and so a list of intersections is returned. Each list item contains a `geometry` attribute, which \
  is an intersecting piece of the input geometry, and a `sampled` attribute, which is the value \
  returned from the coverage at that specific location.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_intersections.description.3 = \
  Note that when building a simple model, the `sample_closest` function might be easier to use instead, \
  as that lets you work with a single sampled value instead of a list of values.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_values.description = \
  Selects all the values from a coverage that intersect with the given geometry.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_values.description.1 = \
  Similar to `sample_intersections` except this function only returns the values, not the intersecting geometry. \
  This function will also return matches where geometries touch, as well as any intersecting/overlapping geometry.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_centroid.description = \
  Select a single value from a coverage by sampling at the geometry's centroid (centre point). \
  This function will return null if there is no sample at the centroid even if there are samples \
  that intersect other parts of the geometry.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_one.description = \
  Deprecated: `sample_one` is an alias to `sample_closest`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_closest.description = \
  Selects a single value from a coverage. If the geometry intersects with multiple values in the coverage then \
  the value closest to the geometry centroid is chosen. If nothing is found and 'buffer-distance' is specified \
  (in metres) then the geometry is buffered (enlarged) by that amount and the coverage is sampled again, but \
  this time the value closest to the geometry is chosen.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_closest.description.1 = \
  Note: buffering is done with an estimated metric-to-map-unit distance, which can be inaccurate for degree (lat/long) \
  based projections.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_n_closest.description = \
  Returns a list of `n` values and geometries from a coverage,  sorted closest first.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.sample_n_closest.description.1 = \
  Each list item item contains a `geometry` attribute, which is the geometry of the underlying coverage (e.g. a point stored in \
  a nearest-neighbour coverage), and a `sampled` attribute, which is the value returned from the coverage at that \
  specific location.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.scoped.description = \
  Internal/Expert function for applying an expression to a specific scope, excluding any outer scope, contrary to how \
  most RiskScape functions work.  Useful for testing/debugging scenarios.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.segment.description = \
  Cut geometries up by a distance specified in metres (m). \
  Linestrings are cut into pieces of at most `distance` metres in length. \
  Polygons are cut using a grid - each grid cell is a square, where each side is `distance` metres in length. \
  E.g. cutting a polygon by 100m will result in grid cells that are 100m x 100m (10000m²) squares. \
  The grid is aligned to each polygon's centroid, so there is no guarantee that each segment will have a particular area. \
  E.g. cutting a 10001m² polygon by 100m may result in four 2500.25m² segments.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.segment_by_grid.description = \
  Cut geometries up by a grid that has a mesh size of distance specified in metres (m). \
  The grid is aligned with the `to-align` parameter which may be a point or a coverage (in which case the lower left \
  corner is aligned to).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.stack_continuous.description = \
  Aggregate function for 'stacking' a set of continuous curves in to a single one.  Can be used as an optimization \
  for probabilistic modelling to cut down on the number of function calls - the function can be called once per hazard \
  site (instead of once per exposure) by grouping all the exposures by site and then stacking their consequence curves \
  using this function.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.starts_with.description = \
  Returns true if the given `test` string argument starts with the `prefix` argument. False otherwise

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.str.description = \
  Returns a text representation of the given argument

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.str_find.description = \
  Returns true if the `haystack` argument contains the `needle` argument sub-string

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.str_length.description = \
  Returns the length of a Text argument

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.switch.description = \
  Returns a result based on the `on` value. The given cases are searched for one that contains the \
  `on` value in the `in` list. If the value is matched then `return` is returned else searching \
  continues. The `default` value is returned if there are no matches.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.switch.description.1 = \
  Note that the `cases` argument must be constant.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.switch.description.2 = \
  E.g `switch(on: 'bicycle', default: 'unknown', cases: [{in: ['bicycle', 'motorbike'], return: '2'},{in: ['car'], return: '4'}])` \
  will return '2'.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description = \
  Turns a given list or relation into a 'continuous curve' that can be linearly interpolated.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description.1 = \
  For example, a `damage-curve.csv` file might contain a series of damage state `y` values that \
  correspond to various hazard intensity `x` values. The data-points in that file can be turned \
  into a continuous curve using an expression like: \
  `to_continuous_curve(bookmark('damage-curve.csv'), x-value: row -> row.hazard_intensity, y-value: row -> \
  {row.DS1, row.DS2, row.DS3, row.DS4})`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description.2 = \
  Passing the resulting continuous curve to `apply_continuous()` will then use linear interpolation to determine the \
  damage state for any hazard intensity, based on the data-points in the file, \
  i.e. for any given `x` value (hazard intensity), it will interpolate the corresponding `y` value (damage state). \
  Note that if the x value being interpolated falls outside the data range, then the min or max x value will be used.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description.3 = \
  The x-value and y-value arguments are lambda expressions that extract x and y values from each row of the list or relation. \
  `x-value` must yield a single numeric value (either `floating` or `integer`), \
  whereas `y-value` can either be a single number or a struct of multiple numbers.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description.4 = \
  This function may also be used in a group step by first collecting the results in to a list, then calling \
  `to_continuous_curve` function, e.g. `group(by: climate_scenario, select: {*, to_continuous_curve(to_list(*), \
  x-value: row -> row.hazard_intensity, y-value: row -> row.damage_state)})`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_continuous_curve.description.5 = \
  Can also apply log scale to the x-axis by supplying the option apply_log_to_x.
  
nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description = \
  Produces a coverage from a collection of tuples. The `values` argument is the data to turn into a coverage, \
  and can be either a relation, a constant bookmark id/path, or list of tuples. \
  This function can also be used as an aggregate function to collect tuples (i.e. in a 'group' pipeline step).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description.1 = \
  The produced coverage can be sampled using one of the sampling functions (e.g. `sample_intersections`, \
  `sample_centroid` or `sample_closest`).  The coverage is constructed by adding all of the tuples into a \
  spatial index, which is queried for matching tuples when sampled. \
  The tuples in the coverage must contain a single geometry member that is spatially referenced.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description.2 = \
  There are two types of index that can be constructed, 'intersection' and 'nearest_neighbour', which can be \
  specified by the `index` option, e.g. `to_coverage(values, options: {index: 'intersection'})`. \
  The default `index` is 'intersection'.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description.3 = \
  The `intersection` index is most appropriate for indexing polygonal features. The sampling \
  operation will query the index for any intersecting features, and return those that match according to the \
  semantics of the sampling operation that was used. \
  By default, RiskScape will optimize the index's performance for polygon geometries, however you can disable this \
  by setting the `intersection_cut` option to false. Disabling this option can be required in the rare case where \
  the input geometry is a mix of types (e.g. points and polygons).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description.4 = \
  The `nearest_neighbour` index is best when indexing point features.  A sampling operation will query \
  the index for the nearest feature's point (with a max distance cut off).  Only `sample_centroid` is currently \
  supported for this type of index.  The cutoff distance must be supplied as the `nearest_neighbour_max_distance` \
  option. E.g to use a nearest neighbour index with a cutoff of one kilometre use \
  `to_coverage(tuples, options:  {index: 'nearest_neighbour', nearest_neighbour_max_distance: 1000})`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_coverage.description.5 = \
  The simplest example of using this function in a pipeline is with bookmark data (typically a relation), e.g. \n\
  sample_centroid(building.geom, to_coverage('hazard')) \n\
  Note that the above sampling operation will work regardless of whether the 'hazard' bookmark is \
  vector data (i.e. a relation) or raster data (i.e. already a coverage).

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_lookup_table.description = \
  Aggregate function that collects tuples and produces a lookup table.  A lookup table allows values to be looked up \
  using the `lookup` function in an expression, which can be a simple way of accessing tabular data in an expression.\

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_lookup_table.description.1 = \
  When used as an aggregate expression (i.e. in a `group` step), `key` and `value` arguments are used to derive the \
  keys and values from each tuple.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_lookup_table.description.2 = \
  An optional `options` argument can be given, which allows a `unique` option to be specified.  When `unique` is \
  `false` (the \
  default), the lookup table assumes that multiple values can be mapped to each key, and so it keeps a list of values \
  for each key.  If `unique` is `true`, then only one value can exist for each key, and \
  evaluation will fail if more than one value is seen for each key.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_lookup_table.description.3 = \
  Group by example: \
  `input('events') -> group(to_lookup_table(key: event_id, value: *, options: {unique: true}))` - this creates a \
  lookup table of events keyed by the event's id.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_lookup_table.description.4 = \
  This function can also be used outside of a `group` step to turn a list of data into a lookup table. For example: \
  `to_lookup_table(map(events, event -> {key: event.id, value: event}), options: {unique: true})` - this \
  creates a lookup table from a list of events, without needing to unnest the list and send it to a `group` \
  step.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_relation.description = \
  Converts a coverage into a relation so that each data point in the coverage can be treated as a separate row of data. \
  This can be useful when dynamically loading a series of rasters as exposure data, such as population rasters.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.to_relation.description.1 = \
  This function can be combined with the `unnest` pipeline step to turn the converted relation into individual rows of data. \
  For example, `select({*, to_relation(bookmark('my-raster')) as grid_cell}) -> unnest(grid_cell)`

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.trapz.description = \
  Estimates the area under the curve provided by `function` between points `a` and `b`. Estimation is performed \
  using the trapezoidal rule (https://en.wikipedia.org/wiki/Trapezoidal_rule)

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.trapz.description.1 = \
  The provided function should accept a single floating argument and also return a floating result.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.trapz.description.2 = \
  Note that for average annual loss (AAL) calculations, it is simpler to use the `aal_trapz` function.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.triangulate.description = \
  Convert a list of samples into a single value using barycentric interpolation.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.triangulate.description.1 = \
  Works with `sample_n_closest` to interpolate sampled values from a coarse grid to increase accuracy, for example \
  `triangulate(sample_n_closest(building, shaking_data, 3))`.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.triangulate.description.2 = \
  If the given list of samples is empty, the function returns null. If it contains a single item, that sample's value is \
  returned. If the list contains two samples, linear interpolation is performed. If the list contains more than three \
  samples, only the first three are used - this function assumes the list is already sorted by distance, like \
  `sample_n_closest` does.

nz.org.riskscape.engine.function.IdentifiedFunction.by-id.zip.description = \
  Produces a new list by calling `lamba` with the nth elements from each input list, until the shortest \
  input list is exhausted. \
  For example the `lamba` expression `(l1, l2) -> l1 + l2` would result in a list containing the \
  sum of nth elements of each input list.
