# HttpSecret
nz.org.riskscape.engine.auth.HttpSecret.params.id = \
  Identifies this secret uniquely.  This is taken from the INI file section header, .e.g. `[riskscape.nz]`

nz.org.riskscape.engine.auth.HttpSecret.params.hostname = \
  The `hostname` of the remote server that this secret applies to, i.e. this secret is used for authenticating \
  with this server. If not provided the INI file section header, .e.g. `[riskscape.nz]` will be used instead.

nz.org.riskscape.engine.auth.HttpSecret.params.allow-http = \
  When set to true, this secret can be transmitted over an insecure HTTP connection.  Setting this to true can expose \
  your secret to others on the network, and is not advised for use outside of a private network.

nz.org.riskscape.engine.auth.HttpSecret.params.allow-subdomains = \
  Use this secret with subdomains of the `hostname` it applies to.  For example, if `hostname` is `riskscape.nz`, then \
  the secret will also apply to `sites.riskscape.nz`.

# HttpHeaderSecret
nz.org.riskscape.engine.auth.HttpHeaderSecret.description = \
  Use an HTTP header to authenticate.  A well known header is used to pass your secret to the server each time you \
  fetch data from the server.

nz.org.riskscape.engine.auth.HttpHeaderSecret.params.header-name = \
  The name of the HTTP header to add, e.g. `Authorization`

nz.org.riskscape.engine.auth.HttpHeaderSecret.params.secret-header-value = \
  The actual secret value to pass in the header, such as an API token.

# EnlargeStep
nz.org.riskscape.engine.steps.EnlargeStep.description = \
  Enlarges a geometry by a specified amount. Primarily intended for use with line geometries.

nz.org.riskscape.engine.steps.EnlargeStep.params.distance = \
  The distance (in metres) to enlarge the geometries.

nz.org.riskscape.engine.steps.EnlargeStep.params.geom-expression = \
  Expression to the geometry to enlarge (or a struct that contains a geometry member). If \
  not specified then the first geometry found will be the one to be enlarged.

nz.org.riskscape.engine.steps.EnlargeStep.params.mode = \
  Controls how geometries are enlarged. Refer to `buffer` function for a description of \
  how mode affects the enlarged geometry.

nz.org.riskscape.engine.steps.EnlargeStep.params.remove-overlaps = \
  When true, overlaps that exist after enlarging the geometries will be removed.  Overlaps are removed \
  for each geometry by 1) finding all other geometries that overlap it, 2) removing the overlap from \
  either the geometry being checked or the other geometry in an alternating manner (this is to prevent \
  all overlaps being removed from the first geometry). 3) If removing an overlap would render any of \
  the resulting geometries empty, then the overlap is not removed.

# FilterStep

nz.org.riskscape.engine.steps.FilterStep.description = \
  Applies a filter to results, removing those that fail the filter test.

nz.org.riskscape.engine.steps.FilterStep.params.filter = \
  A boolean-yielding expression. If the expression evaluates to FALSE, then the item is removed from the results.

# GroupByStep

nz.org.riskscape.engine.steps.GroupByStep.description = \
  Apply an aggregate expression across optionally grouped input values, e.g. \
  `group(count(exposures), by: damage_state)`. \
  Similar to the use of `GROUP BY` in SQL, use RiskScape's aggregate functions to perform operations like `sum` and \
  `count` on grouped tuples to compute a single value for each group.

nz.org.riskscape.engine.steps.GroupByStep.params.select = \
  The aggregation expression to apply to input, e.g. `{sum(value) as total}`.  Members of the group by \
  expression can be referenced here, e.g. `group({category, sum(value) as total}, by: category)` is valid.

nz.org.riskscape.engine.steps.GroupByStep.params.by = \
  An expression that groups the input so that each group is aggregated individually.  For example `group({category, \
  sum(value) as total}, by: category)` would group all inputs by their category and calculate a total value for each \
  category

# JoinStep
nz.org.riskscape.engine.steps.JoinStep.description = \
  Joins two relations together. The relation can be any chain of pipeline steps. \
  E.g `input('exposures') -> join(rhs: <- input('hazards'))` will join all of the \
  exposures to all of the hazards.

nz.org.riskscape.engine.steps.JoinStep.description.1 = \
  It is also possible to supply inputs to the join step as named inputs. \
  Use `lhs` for the left hand side (LHS) relation, and `rhs` for the \
  right hand side (RHS) relation, e.g. `prev_step -> join.lhs`.

# use BaseStep here to reuse keys for JoinLoopStep as well
nz.org.riskscape.engine.steps.BaseStep.params.on = \
  Condition that evaluates whether a row of data from each relation 'matches' and should be joined together.  Defaults \
  to `true`, which will join each row from the `rhs` to the `lhs`, also known as a cross-product or Cartesian join.

nz.org.riskscape.engine.steps.BaseStep.params.join-type = \
  Specifies what to do with left hand side (LHS) rows when no right hand side (RHS) row matches. One of:\n\
  - INNER: any non-matching rows are dropped (the default). \n\
  - LEFT_OUTER: include any non-matching rows from the LHS.

nz.org.riskscape.engine.steps.BaseStep.params.initial-index-size = \
  Sets the initial capacity of the index. This can improve performance when the initial size is large \
  enough that the index does not need to grow as items are added. Setting to a large value will use more memory.

nz.org.riskscape.engine.steps.BaseStep.params.rhs = \
  Supply the RHS from a pipeline chain instead of using the named input.

# RelationInputStep

nz.org.riskscape.engine.steps.RelationInputStep.description = \
  Makes input available to the pipeline. Input is most often from a relation (such as a Shapefile or CSV) \
  but may also come from the `value` expression.

nz.org.riskscape.engine.steps.RelationInputStep.params.relation = \
  The source data to yield.  Normally this is the ID of a bookmark from your project, but can also be a \
  filename/URL.

nz.org.riskscape.engine.steps.RelationInputStep.params.value = \
  An expression that provides a single input item. Used instead of `relation`. E.g the following would \
  create an input with a single tuple `input(value: {make: 'Toyota', model: 'Corolla'})`. \
  Note that `limit` and `offset` are ignored when `value` is used.

nz.org.riskscape.engine.steps.RelationInputStep.params.name = \
  Nest each tuple from the relation in a parent tuple.  More simply put, if \
  given, this will be the name of the attribute that wraps each tuple from the \
  relation.  For example, if your source has attributes named `foo` and `bar`, setting name to `baz` will give \
  results named `baz.foo` and `baz.bar`.  This can be useful for distinguishing the source data from other \
  computed data in your pipeline.

nz.org.riskscape.engine.steps.RelationInputStep.params.limit = \
  Optionally limit the number of tuples that are yielded from the input data.  Similar to an SQL limit.

nz.org.riskscape.engine.steps.RelationInputStep.params.offset = \
  Optionally skip a number of tuples that are yielded from the input data.  Similar to the offset part in an \
  SQL limit clause

# SaveStep
nz.org.riskscape.engine.steps.SaveStep.description = \
  Save results out to files or other supported storage systems.

nz.org.riskscape.engine.steps.SaveStep.params.name = \
  A name to give to the output.  May differ to the name ultimately given to any created files, depending on the \
  format or the storage location (e.g. files saved to a directory with existing files may be renamed to avoid \
  over-writing any existing files).

nz.org.riskscape.engine.steps.SaveStep.params.format = \
  The file format to use when saving data. See `riskscape format list` for the available formats. \
  Defaults to `csv` if no geometry is present in the output, `shapefile` if there is.

nz.org.riskscape.engine.steps.SaveStep.params.options = \
  Format-specific options. See `riskscape format save options FORMAT` for supported options.

# SelectStep
nz.org.riskscape.engine.steps.SelectStep.description = \
  Produces a new output tuple by applying the given select expression to the input tuple, e.g. \
  `select({*, '$' + str(cost) as "Replacement Cost"})`.  Don't forget to surround your expression with \
  braces (`{` and `}`) if you want to return more than one thing!

nz.org.riskscape.engine.steps.SelectStep.params.select = \
  An expression that maps the input to output.  Output is always a struct, even if only \
  a non-struct value is returned, e.g. select('') will give a struct with a single text member.

nz.org.riskscape.engine.steps.SortStep.description = \
  Produces output that is sorted based on one or more sort-by expressions. \
  The sort step should only be used immediately before a save step. This is to prevent any \
  subsequent steps changing the order because they are being processed in parallel. \
  Caution, output is collected in memory. Sorting large volumes of output may result in failures \
  due to insufficient memory.

nz.org.riskscape.engine.steps.SortStep.params.delta = \
  A lambda expression that calculates the delta between the two tuples that have been \
  sorted. The delta is added into the tuples. For example if the tuples contained a `value` \
  attribute and you wanted to know the difference between tuples you could use \
  `(prev, current) -> current.value - prev.value`

nz.org.riskscape.engine.steps.SortStep.params.delta-attribute = \
  Name the attribute that the delta will be stored in. By default this will be `delta`.

nz.org.riskscape.engine.steps.SortStep.params.delta-type = \
  The type of the delta-attribute. If provided, it will be used to pass the delta from \
  the previous step into the lambda expression (as `prev.delta`). This provides basic \
  support for cascading hazards. Only required when the delta lambda expression uses the delta-attribute

nz.org.riskscape.engine.steps.SortStep.params.direction = \
  May be used to set the sort direction for attributes. `asc` to sort in ascending \
  order, or `desc` to sort in descending order. Any attributes that do not have a direction set \
  in this list will default to ascending. \
  E.g. `['desc', 'asc']`

nz.org.riskscape.engine.steps.SortStep.params.by = \
  The attribute(s) to sort by.  To sort on multiple attributes, use a list \
  of attributes, e.g. `[consequence.loss, exposure.total_value]`

# ForeachStep
nz.org.riskscape.engine.steps.ForeachStep.description = \
  Executes a child pipeline for each item in a list, combining their results (if any) in to a union step.  For example, \
  `foreach(items: ['road', 'rail'], pipeline: <- input($item))` allows a variable number of exposure layers to be \
  added in to the pipeline.

nz.org.riskscape.engine.steps.ForeachStep.description.1 = \
  If none of the child pipelines produce any output, (typically because the child pipeline saves the results of its \
  processing),  then the `foreach` step itself does not produce any.  Attempting to chain another step from the \
  `foreach` step will likely give an error message in this case.

nz.org.riskscape.engine.steps.ForeachStep.description.2 = \
  To pass data from the parent pipeline to the child, chain a step to the `foreach` like so - \
  `input('buildings') -> foreach(items: ['Residential', 'Commercial'], pipeline: <- in -> filter(use_type = $item) -> ...)`.\
  Alternatively, the first step in the child pipeline can refer to any other step in the parent, e.g. \
  `foreach(items: ['Residential', 'Commercial'], pipeline: <- input_buildings -> filter(use_type = $item))`.

nz.org.riskscape.engine.steps.ForeachStep.description.3 = \
  As well as an `$item` parameter (the current element from the `items` list), an `$index` parameter is made available \
  to the child pipeline. These can be used in any expression within the child pipeline, e.g. \
  `input($item) -> select({*, index: $index})`

nz.org.riskscape.engine.steps.ForeachStep.params.items = \
  The items to iterate over, e.g. ['road', 'rail'].  Can be a parameter, but must be constant.  Each item is \
  made available to the child pipeline as `$item`, and an `$index` parameter contains the list position (or member name \
  if items was a struct). \
  Items may be a struct, in which case each struct attribute becomes an item and the attribute name is \
  used as the index. \
  If items is not a list or a struct then it is treated as a single item.

nz.org.riskscape.engine.steps.ForeachStep.params.pipeline = \
  The child pipeline to execute for each item. To receive input from an outer pipeline step, the child pipeline \
  must start with a step reference (e.g. `<- in -> ...`).

# SubpipelineStep
nz.org.riskscape.engine.steps.SubpipelineStep.description = \
  Execute another pipeline as part of this pipeline, e.g. `input('buildings') -> subpipeline('approximate-foundation-type.txt', {seed: 0.2}) -> ...`.  A sub-pipeline can help to break up \
  a complicated pipeline, or share common structure between models.  Sub-pipelines \
  can be used for input, output or both.

nz.org.riskscape.engine.steps.SubpipelineStep.description.1 = \
  To send tuples to a sub-pipeline, chain a step to it like so - \
`select({...}) -> subpipeline(...)`.  The sub-pipeline must contain a step referenced named `in` to receive tuples from the outer pipeline, e.g. `in -> select({...}) -> ...`

nz.org.riskscape.engine.steps.SubpipelineStep.description.2 = \
  To receive tuples from a sub-pipeline, chain a step from it like so - `subpipeline(...) -> select({...})`.  The sub-pipeline will send tuples from any non-terminal step it contains to the outer pipeline, or which ever step in the sub-pipeline is named `out`.

nz.org.riskscape.engine.steps.SubpipelineStep.params.id = \
  A sub-pipeline id or file/URI to a location containing a sub-pipeline resource.

nz.org.riskscape.engine.steps.SubpipelineStep.params.parameters = \
  A tuple of parameters to pass to the sub-pipeline, e.g. `parameters: {damage_threshold: 0.2}`. \
  Any parameters in the sub-pipeline will be set, just like with normal model parameters in a model \
  pipeline.  Missing parameters will result in an error, extra parameters will produce a warning.

# UnionStep
nz.org.riskscape.engine.steps.UnionStep.description = \
  Combines two pipeline chains into one. For example, this can combine multiple input relations into one. \
  The resulting tuple is a combination of the attributes produced by each of the input steps. \
  For best results, the input steps should produce the same attribute names and types. \
  If an attribute is present in one branch but not another, it will become Nullable. \
  If the attribute is present, but has a different type, then its type may become 'Anything'.

# UnnestStep
nz.org.riskscape.engine.steps.UnnestStep.description = \
  Transforms a list, so that every item in the list becomes a separate row of data. \
  The transformation happens 'in place', such that the list attribute in the pipeline data is replaced by the list item. \
  When multiple lists are specified, the Nth row of data produced will contain the Nth item from each list \
  (similar to `zip()` in Python, except null values will be used if one list is shorter than the other).

nz.org.riskscape.engine.steps.UnnestStep.description.1 = \
  Unnest can also apply to relations, which lets you dynamically load relational data from multiple files into the pipeline. \
  This is an advanced concept - refer to the documentation for examples of how to do this.

nz.org.riskscape.engine.steps.UnnestStep.params.to-unnest = \
  The list or relation attributes to expand, e.g. `unnest(list)` or `unnest([list1, relation1])` to unnest more than \
  one list or relation at once.

nz.org.riskscape.engine.steps.UnnestStep.params.index-key = \
  Adds an additional attribute, with the given name, to each row of data. \
  This attribute will have a unique numeric index representing the Nth item produced by the list or relation

nz.org.riskscape.engine.steps.UnnestStep.params.emit-empty = \
  False by default, which means a list that is empty or null will *not* produce any rows of data. \
  However, the row of data containing the empty/null list may also contain other important data, \
  which would be lost. If set to true, an empty list will always emit a single row of data, \
  containing a null list item.

# Base Bookmarks

nz.org.riskscape.engine.data.BaseBookmarkResolver.params.location = \
  location of the bookmarked resource. May be a relative file or URI, content depends on the bookmark resolver

nz.org.riskscape.engine.data.BaseBookmarkResolver.params.format = \
  sets the format of the bookmarked resource.  Required if format cannot be inferred from the location.

nz.org.riskscape.engine.data.BaseBookmarkResolver.params.description = \
  may be used to describe content of bookmarked resource

nz.org.riskscape.engine.data.BaseBookmarkResolver.params.requires-secret = \
  Useful for shared projects where an https location requires authentication in order to access the data. \
  This indicates to other users that they need to supply an API key (via secrets.ini) in order to use the bookmark.

# FeatureSourceBookmarkResolver.FeatureSourceBookmarkParams

nz.org.riskscape.engine.data.relation.FeatureSourceBookmarkResolver.params.linearize-tolerance = \
  Advanced option to enable the conversion of curved geometries to linear and set the tolerance to use. \
  Setting to zero will enable conversion with the highest accuracy. \
  Search documentation for `Curved Geometries` for more information.

# RelationBookmarkParams

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.skip-invalid = \
  Any invalid rows or records in the input data file will be skipped and a warning displayed \
  when this option is set to true for a bookmark. \
  When set to false, an invalid row or record in the input data will \
  cause an error that will stop the model or pipeline from running to completion.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.validate-geometry = \
  Controls the detection and fixing of invalid geometries. \n\
  - ERROR - Check geometries are valid and try to fix any that are invalid.  If the geometry cannot be fixed \
            then the tuple is treated as invalid. See the `skip-invalid` parameter for more information on \
            invalid tuples. \n\
  - WARN  - Checks geometries are valid and try to fix any that are invalid. If the geometry cannot be fixed \
            then give a warning. \n\
  - OFF   - Geometries are not checked for validity. \n\
  If not set then this option will default to the project's `validate-geometry` setting. \n\
  Invalid geometries can cause problems later on so it is best to detect and then fix them at their source. \
  GIS systems often have tools for fixing invalid geometries, for QGIS see \
  https://www.qgistutorials.com/en/docs/3/handling_invalid_geometries.html \n\
  Note: validating geometry has an impact on performance especially for complex polygonal geometries. \
  Disabling geometry validation for bookmarks that are known to have valid geometry would be sensible.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.type = \
  Set a target type for the data that comes out of this bookmark.   Allows a defined riskscape type to be \
  imposed on the data.  Raw values from the underlying data source are coerced to the target type.  See also \
  map-attribute for information on manipulating source data in to the required type

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.map-attribute = \
  Attribute prefix for bookmarks that allows attributes to be set to the target type via an expression \
  on the source type, e.g: \n \n\
  map-attribute.name=THE_NAME \n\
  map-attribute.geometry=centroid(the_geom) \n \n\
  The source type will be whatever the underlying data format has inferred from the source data schema.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.set-attribute = \
  Used to add or change attributes in the bookmarked data. Similar to `map-attribute`, except \
  that the `type` is not required.  The value can be either another attribute, or an expression that can incorporate \
  the original data.\n \n\
  For example, a `geom` attribute could be created with `set-attribute.geom=create_point(x,y)`.  Or, a csv column \
  could be converted in to a number with something like `set-attribute.value = int(value)`.\n \n\
  Note that the resulting type is inferred from the given expression.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.crs-name = \
  Sets or replace the coordinate reference system of a relation to the one identified by this code.  This does \
  not reproject the geometry, it just adjusts the metadata of the data.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.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. \
  This option affects how co-ordinates are read/written by Riskscape. \
  By default Riskscape will use the axis ordering defined in the CRS. Setting this option to true will \
  mean RiskScape reads the first value of each co-ordinate as longitude, regardless of CRS-defined axis order. \
  See http://docs.geotools.org/latest/userguide/library/referencing/order.html for more information.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.rasterize = \
  Set to true to rasterize the vector data before passing it to any model.  This can speed up query \
  processing by a large amount, but is at the cost of a less accurate model

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.rasterize-expression = \
  An expression used to extract a value from the relation we are rasterizing.  This value is then yielded \
  when the raster is sampled for a point that lies within a feature's pixel representation

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.rasterize-scale-factor = \
  A factor to apply when determining raster size, such that each pixel represents (1 / scale factor)\u00b2 number \
  of CRS units.  If scale factor is 0.01 and CRS units are metres, then each pixel will represent 100x100m \
  (10,000m\u00b2)

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.rasterize-grid-size = \
  Number of metres, squared, to allocate to each pixel.  If grid size is 100, then \
  each pixel will represent 100x100m (10,000m\u00b2), Note that if the source relation CRS is \
  based on degrees, then the actual pixels produced will not be square and will distort as latitude \
  increases.

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.layer = \
  Select a particular layer from the data source by name.  If this is not set and a data source has multiple \
  layers available, one is selected arbitrarily

nz.org.riskscape.engine.data.relation.RelationBookmarkResolver.params.filter = \
  Apply an arbitrary filter to the source data to filter the bookmark's data at source.

# CoverageFileBookmarkResolver

nz.org.riskscape.engine.data.coverage.CoverageFileBookmarkResolver.params.crs-name = \
  Sets or replace the coordinate reference system of a relation to the one identified by this code.  This does \
  not reproject the geometry, it just adjusts the metadata of the data.

nz.org.riskscape.engine.data.coverage.CoverageFileBookmarkResolver.params.crs-longitude-first = \
  When a CRS has been assigned via the `crs-name` parameter, this attempts to change the axis ordering \
  that co-ordinates are read in. By default, RiskScape will assume coverage files have LONG, LAT ordering. \
  Setting this option to false means Riskscape will use the axis ordering defined in the CRS (often LAT, LONG). \
  See http://docs.geotools.org/latest/userguide/library/referencing/order.html for more information.

nz.org.riskscape.engine.data.coverage.CoverageFileBookmarkResolver.params.layer = \
  Select a particular layer from the data source by name.  If this is not set and a data source has multiple \
  layers available, one is selected arbitrarily

nz.org.riskscape.engine.data.coverage.CoverageFileBookmarkResolver.params.map-value = \
  Applies a custom transformation to the data returned when the coverage is spatially sampled. \
  For example, if the coverage data is in units of gravity (`g`), but your model expects \
  the data to be in `log(g)` units, you can use `map-value = log(value)`. \
  This can also be expessed as a lamda, e.g. `map-value = g -> log(g)`. \
  Note that returning null from the expression will map the result to `NO_DATA`.

nz.org.riskscape.engine.data.coverage.CoverageFileBookmarkResolver.params.sparse-tiff = \
  Applies an optimization with GeoTIFFs to avoid loading tiles that are all no-data.  This gives a large performance \
  impact when sampling layers that are mostly NO_DATA (such as inundation maps). Supports sparse TIFFs (see \
  https://gdal.org/en/stable/drivers/raster/gtiff.html#sparse-files), but can also scan the TIFF's tile index to \
  detect tiles that are all `NO_DATA`.

nz.org.riskscape.engine.join.JoinType.INNER = \
  LHS items are only included when items from the RHS are joined

nz.org.riskscape.engine.join.JoinType.LEFT_OUTER = \
  LHS items are included when no RHS items are joined

nz.org.riskscape.engine.output.CsvFormat.description = \
  Writes data to a CSV output file.

nz.org.riskscape.engine.output.CsvFormat.params.include-geometry = \
  Determines if (and how) geometry attributes are saved. One of: \n\
  - FALSE: geometry attributes are not included \n\
  - TRUE: geometry attributes are included in WKT format \n\
  - CENTROID: only the centroid of any geometry is included in WKT format

nz.org.riskscape.engine.output.GeoJSONFormat.description = \
  Writes spatial data to a GeoJSON output file.

nz.org.riskscape.engine.output.GeoTiffFormat.description = \
  Writes spatial data to a GeoTIFF output file.

nz.org.riskscape.engine.output.KmlFormat.description = \
  Writes spatial data to an output file in KML format.

nz.org.riskscape.engine.output.ShapefileFormat.description = \
  Writes spatial data to an output file in shapefile format.

nz.org.riskscape.engine.output.ShapefileGeotoolsFormat.description = \
  Deprecated: Writes spatial data to a file in shapefile format.

nz.org.riskscape.engine.output.GeoTiffFormat.description = \
  Writes spatial data to a `geotiff` file.

nz.org.riskscape.engine.output.GeoTiffFormat.description.1 = \
  For each row of data, or 'feature', all pixels that lie beneath the feature's geometry \
  are set to the feature's value. \
  If several different features overlie the same pixel, then the value for that pixel will be \
  determined by the `pixel-statistic` strategy in use.

nz.org.riskscape.engine.output.GeoTiffFormat.params.grid-resolution = \
  The size of each pixel in metres. \
  For example, if grid-resolution is 100, then each pixel will represent 100x100m (10,000m²). \
  Note that if the CRS of the geometry being saved is based on degrees, such as EPSG:4326, \
  then the actual pixels produced will not be exactly square and will distort as latitude increases.

nz.org.riskscape.engine.output.GeoTiffFormat.params.bounds = \
  Expression that yields a polygon that defines the extent of the GeoTIFF file. \
  For example: `bounds(bookmark('foo.tif'))`. \
  Any features that fall outside the bounds will be ignored.

nz.org.riskscape.engine.output.GeoTiffFormat.params.value = \
  The value to write to the GeoTIFF pixel(s) that lie beneath each feature. \
  This can be any RiskScape expression, such as `consequence.Life_Safety_Risk` or `exposure.Repl_Cost`. \
  If not provided, the first numeric value found will be used.

nz.org.riskscape.engine.output.GeoTiffFormat.params.geometry = \
  The geometry to use when writing the GeoTIFF, if multiple geometries are present. \
  If not provided, the first geometry value found will be used.

nz.org.riskscape.engine.output.GeoTiffFormat.params.pixel-statistic = \
  Determines how pixel values are set when multiple features overlap the same pixel. One of: \n\
  - OVERWRITE: sets the pixel to the value of the last feature written \n\
  - MAX: sets the pixel to the maximum value seen across any overlapping features \n\
  - MIN: sets the pixel to the minimum value seen across any overlapping features \n\
  - MEAN: combines the values for any overlapping features and uses the average \n\
  - SUM: combines the values for any overlapping features and uses the total\n

nz.org.riskscape.engine.output.GeoTiffFormat.params.template = \
  A text-string path to an existing GeoTIFF file to use as a template for the new output GeoTIFF file. \
  The grid-resolution, bounds, and CRS of the template GeoTIFF will be used, \
  and so the 'grid-resolution' and 'bounds' options can be omitted \
  (specifying these options will override the template's setting). \
  The grid-resolution is based on the pixel height of the template GeoTIFF, \
  and so may not match the template GeoTIFF exactly if the template's pixels are not square

nz.org.riskscape.engine.output.ZippedShapefileFormat.description = \
  Writes spatial data using the `shapefile` format which is bundled into a zip output file.

nz.org.riskscape.engine.output.ZippedShapefileFormat.params.compression = \
  Set the compression level for the zip. One of: \n\
  - DEFAULT: good compromise between file size and compression time \n\
  - SMALLEST: reduces file size at the cost of time \n\
  - FASTEST: reduces time to compress at the cost of time \n\
  Note that compression results can vary a lot depending on the content of \
  the shapefiles being compressed.

#
# Types
#

nz.org.riskscape.engine.types.Anything.description = \
  A permissive type that has no constraints on what values may \
  be used to populate it, i.e. no type-checking is done. \
  Could be useful if passing a function input straight to output \
  without modification, i.e. the input's type doesn't concern you

nz.org.riskscape.engine.types.Bool.description = \
  A truth value. Possible values are true or false. \
  Note that when reading input data from a CSV file, "true" will be true and \
  any other text will be false. Wraps a java.lang.Boolean type


nz.org.riskscape.engine.types.ConstType.description = \
  Advanced type for representing a type and its constant value, typically as a \
  result of using the `const` function.

nz.org.riskscape.engine.types.ConstType.category = engine type

nz.org.riskscape.engine.types.CoverageType.description = \
  A raster-like dataset that can be sampled to produce the wrapped type

nz.org.riskscape.engine.types.Date.description = \
  Stores a specific instant in time. Wraps a java.util.Date type

nz.org.riskscape.engine.types.Decimal.description = \
  Similar to floating, but may have better precision when dealing with floating-point \
  arithmetic. However, decimals can be slower and more memory-intensive to use. \
  Wraps a java.math.BigDecimal type

nz.org.riskscape.engine.types.Enumeration.description = \
  Allows data that is coded to an integer value in source files to be mapped to a \
  well-known string form. E.g. the following .ini file declaration will transform input \
  data so that '1' becomes 'wood', '2' becomes 'steel', and '3' becomes 'concrete'.\n \
  `type = enum('wood', 'steel', 'concrete')`

nz.org.riskscape.engine.types.Floating.description = \
  Stores a real number that can have a fractional part. E.g. 3.14, -87.0, 0.1333. \
  Useful for processing most numeric data. Wraps a java.lang.Double type

nz.org.riskscape.engine.types.Geom.description = \
  Contains a geometry value. If the value is coerced from a string, \
  then it is assumed to be in Well Known Text (WKT) format. \
  Wraps a java org.locationtech.jts.geom.Geometry type

nz.org.riskscape.engine.types.GeomType.Line.description = \
  Contains a line string geometry value. If the value is coerced from a string, \
  then it is assumed to be in Well Known Text (WKT) format. \
  Wraps a java org.locationtech.jts.geom.LineString type

nz.org.riskscape.engine.types.GeomType.Point.description = \
  Contains a point geometry value. If the value is coerced from a string, \
  then it is assumed to be in Well Known Text (WKT) format. \
  Wraps a java org.locationtech.jts.geom.Point type

nz.org.riskscape.engine.types.GeomType.Polygon.description = \
  Contains a polygon geometry value. If the value is coerced from a string, \
  then it is assumed to be in Well Known Text (WKT) format. \
  Wraps a java org.locationtech.jts.geom.Polygon type

nz.org.riskscape.engine.types.MultiGeom.description = \
  Contains a multi geometry value. If the value is coerced from a string, \
  then it is assumed to be in Well Known Text (WKT) format.

nz.org.riskscape.engine.types.Integer.description = \
  Stores a whole number between -2**63 and 2**63 - 1. E.g. 1, -23, 65047. \
  Wraps a java.lang.Long type

nz.org.riskscape.engine.types.LambdaType.description = \
  Represents a lambda expression in a function's type signature.

nz.org.riskscape.engine.types.LambdaType.category = engine type

nz.org.riskscape.engine.types.Nullable.description = \
  Wraps another underlying type to make it clear that a value might not be present. \
  Null can mean nothing, or undefined. For example, the hazard parameter for a \
  model function should be nullable, because null will be used if there is no spatial \
  intersection between an asset and a given hazard

nz.org.riskscape.engine.types.RSList.description = \
  An ordered sequence of values. Useful for processing a series of \
  hazard measurements, such as flood velocity or ground acceleration. \
  Lists have a type, specified when you declare it, e.g. a list of \
  floating-point numbers is: type = list(floating)

nz.org.riskscape.engine.types.Smallfloat.description = \
  Like `floating`, but stored with only half as much (32 bits) precision.  Useful for storing large volumes of \
  numeric data where such a large degree of accuracy is not required.  Wraps the java.lang.Float type.

nz.org.riskscape.engine.types.Text.description = \
  Can contain any value that can be represented as text. Wraps a java.lang.String type. \
  Use the `str()` function to convert from another type to text

nz.org.riskscape.engine.types.WithinRange.description = \
  Constrains a type's values to fall within a defined numeric range. \
  You must specify the numeric type (integer, floating, or decimal) and the \
  minimum and maximum allowable values. E.g. for data that must be a \
  whole number between 1 and 100, use a .ini file type like:\n \
  type = range(integer, 1, 100)

nz.org.riskscape.engine.types.WithinSet.description = \
  Constrains a type's values to fall within a fixed set of values. \
  You must specify the underlying type and the allowable values. \
  This can be useful when your input data is coded to a known set of values. \
  E.g. defining a 'meal' type in your .ini file might look like:\n \
  type = set(text, 'breakfast', 'lunch', 'dinner')\n\
  Note that trying to use 'brunch' as a meal would then result in an error

nz.org.riskscape.engine.types.Struct.description = \
  A structured type that contains other ordered, named values of specific types. \
  Structs are a convenient way for a model to deal with input and output data. \
  In programming terms, Structs could also be thought of as a dictionary. \
  E.g. to declare a .ini file struct with a numeric ID and a text-based name, use:\n \
  type = struct(id: integer, name: text)\n\
  Use '.' to reference a named member of a Struct, e.g. to access the ID value of \
  a Struct called 'asset', use 'asset.id'

nz.org.riskscape.engine.types.RelationType.description = \
  Represents a data-set, such as an entire CSV or shapefile

nz.org.riskscape.engine.types.SimpleType.category = simple type

nz.org.riskscape.engine.types.Struct.category = complex type

nz.org.riskscape.engine.types.Geom.category = geometry type
nz.org.riskscape.engine.types.GeomType.category = geometry type
nz.org.riskscape.engine.types.MultiGeom.category = geometry type

nz.org.riskscape.engine.types.WithinRange.category = simple type + validation
nz.org.riskscape.engine.types.WithinSet.category = simple type + validation

nz.org.riskscape.engine.types.Enumeration.category = simple type + mapping

nz.org.riskscape.engine.types.Nullable.category = contains another type
nz.org.riskscape.engine.types.RSList.category = contains another type
nz.org.riskscape.engine.types.CoverageType.category = contains another type

nz.org.riskscape.engine.types.RelationType.category = engine type

#
# Functions
#
IdentifiedFunction.by-id.aggregate_struct.description = \
  Aggregate function for applying aggregate functions to one of more members of a struct, e.g. \
  `group(aggregate_struct(loss, {max_damage: v -> max(v.damage)}), by: region)` will apply max \
  aggregation to the damage attribute of the loss type.  Can also \
  be used in a normal expression to aggregate values from tuples in a list.

IdentifiedFunction.by-id.append.description = \
  Append an element to a list.

IdentifiedFunction.by-id.apply.description = \
  Call a function that is part of the expression scope (rather than by name), e.g. `apply(function, x_value)`.  Used \
  for calling functions that have been created by another function, such as with mathematical modelling functions like \
  curve fitting.

IdentifiedFunction.by-id.apply.description.1 = \
  The first argument, `function` is the function that you wish to call.  This is not the identifier of a function from \
  the your project, but a part of the expression scope, i.e. a member of a tuple.  These are typically returned from \
  some other function creating function.  This function is just a generic way to call any function when it is part of \
  your data.

IdentifiedFunction.by-id.apply.description.2 = \
  Any extra arguments given to the apply function are taken  to be arguments to the function `apply` calls.  These \
  arguments must match the calling function's types exactly.

IdentifiedFunction.by-id.assert.description = \
  Assert that `condition` is true otherwise a function exception, containing `message`, is raised \
  to terminate model execution.

IdentifiedFunction.by-id.assert.description.1 = \
  Useful to terminate long running models if invalid conditions are encountered.

IdentifiedFunction.by-id.assert_not_null.description = \
  Removes the `nullable` type from the given value, stopping pipeline execution if the value is found to be null.

IdentifiedFunction.by-id.assert_not_null.description.1 = \
  The options may be used to customize the error message should a null value be found.

IdentifiedFunction.by-id.assert_present.description = \
  Asserts that the given argument is present, i.e. it's not 'nothing'. \
  If so, the given argument is returned.

IdentifiedFunction.by-id.assert_present.description.1 = \
  Nothing is a special constant type that is always null. \
  The nothing type is typically only returned by built-in RiskScape functions, such as \
  `get_attr()`. Used in combination, this lets you customize the error message \
  when attributes are missing from the input data, e.g. \
  `assert_present(get_attr(exposure, 'foo'), 'What, no foo?')`

IdentifiedFunction.by-id.assert_present.description.2 = \
  Note that `assert_not_null()` fires if a one-off null value is encountered (i.e. any one row of data), \
  whereas `assert_present()` only fires if a constant null value is present across all rows of data. \
  In other words, `assert_present()` accepts nullable/null attributes but can help detect \
  if an attribute is completely missing from the input data.

IdentifiedFunction.by-id.bbox.description = \
  Implements `bbox` spatial predicate as per \
  https://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#spatial-predicate

IdentifiedFunction.by-id.beyond.description = \
  Implements beyond spatial predicate as per \
  https://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#spatial-predicate \
  except that distance is always specified in metres.

IdentifiedFunction.by-id.buffer.description = \
  Buffer (or enlarge) a geometry by a given distance in metres. By default, buffering has the \
  effect of rounding off corners and line endings in the original geometry, but this can be customized \
  with the optional `options` argument.

IdentifiedFunction.by-id.buffer.description.1 = \
  `options.vertex' affects how external corners are enlarged. Given a 90 degree corner, like \
  on a square, `round` (the default) will round it off, `mitre` will preserve the same sharp corners as the \
  original, `bevel` will cut a 45 degree line across the corner.

IdentifiedFunction.by-id.buffer.description.2 = \
  `options.cap` affects how the end of a line is capped off. `round` (the default) will round it off, \
  `square` will push the ends of the line outward but the end will be square, `flat` is similar to \
  `square` but will not make the line longer.

IdentifiedFunction.by-id.buffer.description.3 = \
  Note that `options.vertex` will not have any effect on line endings - only `options.cap` will. \
  Also note that using a `flat` cap when buffering a point will result in an empty polygon.

IdentifiedFunction.by-id.cast.description = \
  Casts the `value` to the type given by `typedef`.

IdentifiedFunction.by-id.cast.description.1 = \
  Useful to apply a wrapping type. For example `cast('2', 'range(integer, 1, 10)')` returns a range type.

IdentifiedFunction.by-id.cast.description.2 = \
  If the value cannot be cast to the required type then the function call will error.

IdentifiedFunction.by-id.centroid.description = \
  Implements centroid geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.concat.description = \
  Concatenate two lists to create a new list.

IdentifiedFunction.by-id.const.description = \
  Advanced function that attempts to mark the given argument as a constant value.  For \
  use with expression functions that need to use functions that can accept constant arguments, such \
  as `if` or `list_to_columns`.

IdentifiedFunction.by-id.contains.description = \
  Implements contains geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.count.description = \
  Aggregate function for counting all non-null elements in a group. The exception to this is for boolean \
  values where only those that are true are counted. Can also be used with a list in a normal expression.

IdentifiedFunction.by-id.create_point.description = \
  Creates a geometry point using the given x, y coordinates, e.g. `create_point(lat, long)`. Also accepts an optional \
  `crs` argument, which records the expected coordinate reference system of the point, e.g. `create_point(easting, \
  northing, 'epsg:2193')`.

IdentifiedFunction.by-id.crosses.description = \
  Implements crosses geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.disjoint.description = \
  Implements beyond disjoint predicate as per \
  https://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#spatial-predicate

IdentifiedFunction.by-id.dwithin.description = \
  Implements beyond `dwithin` predicate as per \
  https://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#spatial-predicate \
  except that distance is always specified in metres.

IdentifiedFunction.by-id.equals.description = \
  Implements equals geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.expression_text.description = \
  Returns the given expression almost verbatim as a text string. \
  Useful if you need to display a pipeline parameter in a custom error or warning message

IdentifiedFunction.by-id.flatten_struct.description = \
  Converts a struct of structs in to a single-struct by flattening them, for example, `flatten_struct({loss: {damage: 12, \
  state: 'destroyed'}})` becomes `{loss_damage: 12, loss_state: 'destroyed'}`.

IdentifiedFunction.by-id.flatten_struct.description.1 = \
  Optionally accepts a join character (or string) as a second argument to use instead of the default `_` character.

IdentifiedFunction.by-id.flatten_struct.description.2 = \
  If flattening would result in a duplicate attribute name then a trailing index will be added to ensure unique names. \
  E.g `flatten_struct({loss_level: 'high', loss: {level: 99}})` becomes `{loss_level: 'high', loss_level_1: 99}`.

IdentifiedFunction.by-id.filter.description = \
  Filters the given list, returning a new list that contains only those elements that evaluate \
  to `true` for the given test expression, e.g. `filter([1,2,3], i -> i >= 2)` returns `[2, 3]`.

IdentifiedFunction.by-id.geom_from_wkt.description = \
  Create a geometry object from a Well-Known Text (WKT) formatted geometry string, e.g. \
  `geom_from_wkt('POINT (1 2)')`. See \
  https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry for more information about the well-known \
  text format.

IdentifiedFunction.by-id.get_attr.description = \
  A safe way to access an attribute that may or may not be present within a struct. \
  Similar to `dict.get()` in Python.

IdentifiedFunction.by-id.get_attr.description.1 = \
  You can access an attribute from any RiskScape expression using `struct.attribute`, \
  however, this will result in an error if the attribute is not present. \
  Instead, using `get_attr(struct, attribute)` will safely return the attribute if it \
  is present, or null if it is absent.

IdentifiedFunction.by-id.get_attr.description.2 = \
  If a third 'default' argument is specified, that value will be returned instead of null \
  if the attribute is absent.

IdentifiedFunction.by-id.if_null.description = \
  Returns the `test` value if it is non-null, otherwise returns the `else` value. \
  This is useful for supplying a non-null default if a nullable expression yields null.  For example, \
  `if_null(sum(value), 0)` would return 0 if the sum function returns null.

IdentifiedFunction.by-id.inf.description = \
  Returns a floating point number that can be used to represent infinity.

IdentifiedFunction.by-id.intersects.description = \
  Implements intersects geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.keys.description = \
  Similar to the `keys` function in Python, returns a list of the keys in a struct.

IdentifiedFunction.by-id.keys.description.1 = \
  For example `keys({foo: 1, bar: '2'})` returns `['foo', 'bar']`.  Note that the list is returned in the order the keys \
  are defined, not in alphabetical order.

IdentifiedFunction.by-id.keys.description.2 = \
  The resulting list is constant, meaning it can work with functions that require constant arguments.

IdentifiedFunction.by-id.length.description = \
  Returns the number of items in the list.

IdentifiedFunction.by-id.list_get.description = \
  Returns a single element, or a sub-list, from a list. With one index, e.g. `list_get(list, 3)`, returns the element \
  at that position.  With two indices, e.g. `list_get(list, 0, 4)` returns a sub-list from \
  start (inclusive) to end (exclusive).  Behaves the same way as the python slice (`[]`) operation.

IdentifiedFunction.by-id.list_contains.description = \
  Returns true if the given list contains the given item.

IdentifiedFunction.by-id.range.description = \
  Returns a list of integers that increase in value from `start` (inclusive) to `stop` (exclusive).

IdentifiedFunction.by-id.lognorm_cdf.description = \
  Cumulative probability distribution function from a log-normal curve. \
  Where shape is σ (standard deviation) and scale is μ (mean), both as the log of the distribution.

IdentifiedFunction.by-id.lognorm_cdf.description.1 = \
  The equivalent of this function in Excel is: `LOGNORM.DIST(x, scale, shape, 1)`

IdentifiedFunction.by-id.lognorm_cdf.description.2 = \
  Or in Python: `scipy.stats.lognorm(s=shape, scale=exp(scale)).cdf(x)`

IdentifiedFunction.by-id.lognorm_cdf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.LogNormalDistribution \
  cumulativeProbability()` (Javadoc available online)

IdentifiedFunction.by-id.lognorm_pdf.description = \
  Probability Density Function (PDF) for a given point in a normal distribution.  \
  Where shape is σ (standard deviation) and scale is μ (mean), both as the log of the distribution.

IdentifiedFunction.by-id.lognorm_pdf.description.1 = \
  The equivalent of this function in Excel is: `LOGNORM.DIST(x, scale, shape, 0)`

IdentifiedFunction.by-id.lognorm_pdf.description.2 = \
  Or in Python: `scipy.stats.lognorm(s=shape, scale=exp(scale)).pdf(x)`

IdentifiedFunction.by-id.lognorm_pdf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.LogNormalDistribution \
  density()` (Javadoc available online)

IdentifiedFunction.by-id.lognorm_ppf.description = \
  Percent Point Function (`PPF`). Returns the inverse Cumulative Distribution Function from a log normal curve, \
  where x is the desired probability between 0.0 and 1.0

IdentifiedFunction.by-id.lognorm_ppf.description.1 = \
  For example, to find the value in a standard log-normal distribution that 97.72%% of values are \
  less than or equal to, use: `lognorm_ppf(0.9772, 0, 1)`

IdentifiedFunction.by-id.lognorm_ppf.description.2 = \
  The equivalent of this function in Python is: `scipy.stats.lognorm(s=shape, scale=exp(scale)).ppf(x)`

IdentifiedFunction.by-id.lognorm_ppf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.LogNormalDistribution inverseCumulativeProbability()` \
 (Javadoc available online)

IdentifiedFunction.by-id.losses_by_period.description = \
  Calculates loss metrics, such as Probable Maximum Loss, Occurrence Exceedance Probability, \
  or Aggregate Exceedance Probability for specific return periods. (beta)

IdentifiedFunction.by-id.losses_by_period.description.1 = \
  The default mode is `percentile`. In this mode losses are interpolated using a percentile based \
  approach where the percentile is `(1 - 1/RP) * 100`.

IdentifiedFunction.by-id.losses_by_period.description.2 = \
  With the `ranked_closest` mode each loss is assigned an RP. Then the loss closest to the desired RP is returned. \
  If there are not enough event losses for the requested return period, then zero is returned for the event loss.

IdentifiedFunction.by-id.losses_by_period.description.3 = \
  The `investigation-time` argument specifies the effective time period that the losses cover. \
  E.g. `losses_by_period(losses, [1000, 250, 100, 50], investigation-time: 10000) as PML` \
  calculates metrics for a 10,000 year period. The first requested return-period (1000) \
  corresponds to the 10th largest loss (i.e. a 10 in 10000-year event)

IdentifiedFunction.by-id.map_struct.description = \
  Apply the mapper expression to each attribute in the given struct.

IdentifiedFunction.by-id.map_struct.description.1 = \
  For example, to apply a 2%% inflation increase to values in a struct of numbers, you could use: \
  `map_struct({land: 10000, buildings: 20000}, l -> l * 1.02)`.

IdentifiedFunction.by-id.map_struct.description.2 = \
  Also works as an aggregate function.

IdentifiedFunction.by-id.max.description = \
  Returns the largest of two values given.  Also works as an aggregate function for computing the largest value \
  across a set of values

IdentifiedFunction.by-id.maxint.description = \
  Returns the largest positive number (maximum) that the integer type is capable of representing.

IdentifiedFunction.by-id.maxfloat.description = \
  Returns the largest positive number (maximum) that the floating (point) type is capable of representing.

IdentifiedFunction.by-id.maxsmallfloat.description = \
  Returns the largest positive number (maximum) that the smallfloat type is capable of representing.

IdentifiedFunction.by-id.mean.description = \
  Aggregate function for calculating a mean value across a group, e.g. `group(mean(damage), by: region)`.  Can also \
  be used in a normal expression to calculate the mean value of numeric items in a list.

IdentifiedFunction.by-id.measure.description = \
  Will measure either the length or area of a geometry, depending on its geometry type.  Points \
  will always return 0.  Lines will return the length as per `measure_length`.  `Polygon`'s will return the \
  area as per `measure_area`.  `GeometryCollection`s will return the sum of all geometries in the \
  collection

IdentifiedFunction.by-id.measure_area.description = \
  Measure the area of geometry in metres squared (m²). Note that geometries that are specified in degrees \
  are reprojected before being measured. This will lose accuracy for geometries that are larger than 6° in \
  either direction and eventually fail if too big.

IdentifiedFunction.by-id.measure_length.description = \
  Measure the length of a geometry's perimeter in metres (m). Note that geometries that are specified in degrees \
  are reprojected before being measured. This will lose accuracy for geometries that are larger than 6° in \
  either direction and eventually fail if too big.

IdentifiedFunction.by-id.median.description = \
  Aggregate function for calculating the median value across a group, e.g. `group(median(damage), by: region)`.  Can also \
  be used in a normal expression to calculate the median value of numeric items in a list.

IdentifiedFunction.by-id.merge.description = \
  Merge two structs to produce a new struct.  Members of `replace` take precedence over the `original`.  This method \
  is not recursive - that is, any nested structs that share the same attribute name will not be merged, one will win \
  and the other will be replaced completely.

IdentifiedFunction.by-id.remove_attr.description = \
  Returns a copy of `original` with the attribute specified by `remove` removed. `remove` can be either a string or a \
  struct containing the attributes to be removed.

IdentifiedFunction.by-id.remove_attr.description.1 = \
  For example: `remove_attr(exposure, 'geom')` returns a new struct with all the members of exposure except for `geom`, \
  while `remove_attr(exposure, {exposure.geom, exposure.area})` removes both the `geom` and `area` attributes.

IdentifiedFunction.by-id.min.description = \
  Returns the smaller of two values given

IdentifiedFunction.by-id.minint.description = \
  Returns the largest negative number (minimum) that the integer type is capable of representing.

IdentifiedFunction.by-id.minfloat.description = \
  Returns the largest negative number (minimum) that the floating (point) type is capable of representing.

IdentifiedFunction.by-id.minsmallfloat.description = \
  Returns the largest negative number (minimum) that the smallfloat type is capable of representing.

IdentifiedFunction.by-id.mode.description = \
  Aggregate function for calculating the mode (most observed value) across a group, e.g. `group(mode(damage), by: region)`. \
  Can also be used in a normal expression to calculate the mode from a list.

IdentifiedFunction.by-id.modulo.description = \
  Compute the remainder when the `dividend` is divided by the given `divisor`

IdentifiedFunction.by-id.negative_inf.description = \
  Returns a floating point number that can be used to represent negative infinity

IdentifiedFunction.by-id.norm_cdf.description = \
  Cumulative probability distribution function from a normal curve

IdentifiedFunction.by-id.norm_cdf.description.1 = \
  The equivalent of this function in Excel is: NORM.DIST(x, scale, shape, 1)

IdentifiedFunction.by-id.norm_cdf.description.2 = \
  Or in Python: `scipy.stats.norm(mean, stddev).cdf(x)`

IdentifiedFunction.by-id.norm_cdf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.NormalDistribution cumulativeProbability()` \
 (Javadoc available online)

IdentifiedFunction.by-id.norm_pdf.description = \
  Probability Density Function (`PDF`) for a given point in a normal distribution

IdentifiedFunction.by-id.norm_pdf.description.1 = \
  The equivalent of this function in Excel is: NORM.DIST(x, scale, shape, 0)

IdentifiedFunction.by-id.norm_pdf.description.2 = \
  Or in Python: `scipy.stats.norm(mean, stddev).pdf(x)`

IdentifiedFunction.by-id.norm_pdf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.NormalDistribution density()` \
  (Javadoc available online)

IdentifiedFunction.by-id.norm_ppf.description = \
  Percent Point Function (`PPF`). Returns the inverse Cumulative Distribution Function from a normal curve, \
  where x is the desired probability between 0.0 and 1.0

IdentifiedFunction.by-id.norm_ppf.description.1 = \
  For example, to find the value in a standard normal distribution that 97.72%% of values are \
  less than or equal to, use: `norm_ppf(0.9772, 0, 1)`

IdentifiedFunction.by-id.norm_ppf.description.2 = \
  The equivalent of this function in Python is: `scipy.stats.norm(mean, stddev).ppf(x)`

IdentifiedFunction.by-id.norm_ppf.description.3 = \
  Implementation uses `org.apache.commons.math3.distribution.NormalDistribution inverseCumulativeProbability()` \
 (Javadoc available online)

IdentifiedFunction.by-id.nullable.description = \
  Advanced function, useful for testing scenarios, for marking a value's type as nullable without affecting the value \
  itself.  For example, `nullable(1)` returns the value `1`, but the value's underlying type is marked as nullable, \
  even though it's a constant and will never be null.

IdentifiedFunction.by-id.null_of.description = \
  Advanced function, useful for testing scenarios, for setting a null value of a specific type.  For example, \
  `null_of('text')` returns an expression that always evaluates to null but is still typed as text.

IdentifiedFunction.by-id.overlaps.description = \
  Implements overlaps geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.percentiles.description = \
  Aggregate function that returns the values at the desired percentiles across a group, \
  e.g. `group(percentiles(damage, percentiles: [50, 90]), by: region)` will return the 50th and 90th percentiles. \
  Can also be used in a normal expression to return the percentiles of numeric items in a list. \
  Uses the nearest-rank exclusive method.

IdentifiedFunction.by-id.percentile.description = \
  Aggregate function that returns the value at the desired percentile across a group, \
  e.g. `group(percentile(damage, percentile: 90), by: region)` will return the 90th percentile. \
  Can also be used in a normal expression to return the percentile of numeric items in a list. \
  Uses the nearest-rank exclusive method.

IdentifiedFunction.by-id.polynomial.description = \
  Computes a polynomial expression, denoted by the set of coefficients 'c' (starting at x⁰, x, x², etc)

IdentifiedFunction.by-id.polynomial.description.1 = \
  For example, 'polynomial(x: 4, c: [7.0, -5.0, 0.0, 1.0])' will calculate: 7 - 5x + x³ where x=4.

IdentifiedFunction.by-id.polynomial.description.2 = \
  The equivalent of this function in Python is: numpy.polynomial.polynomial.polyval(x, c)

IdentifiedFunction.by-id.polynomial.description.3 = \
  Implementation uses org.apache.commons.math3.analysis.polynomials.PolynomialFunction \
  (Javadoc available online)

IdentifiedFunction.by-id.exp.description = \
  Returns Euler's number (e) raised to the power of the value given. The inverse of log()

IdentifiedFunction.by-id.random_uniform.description = \
  Returns a uniformly distributed random number between start (inclusive) and stop (exclusive).

IdentifiedFunction.by-id.random_uniform.description.1 = \
  For comparison, the equivalent of this function in Python is `random.uniform(start, stop)`. \
  However, note the actual implementation uses `java.util.Random.nextDouble()`.

IdentifiedFunction.by-id.random_uniform.description.2 = \
  Specify a `seed` function argument to make the randomness reproducibly consistent. \
  The `random-seed` RiskScape CLI parameter can also be used to reproducibly change the \
  random number generation, even when a `seed` argument is specified.

IdentifiedFunction.by-id.random_uniform.description.3 = \
  Specifying a `samples` argument will return multiple random numbers as a list.

IdentifiedFunction.by-id.random_choice.description = \
  Picks an item from the list at random, or with an optional weighted probability

IdentifiedFunction.by-id.random_choice.description.1 = \
  This function is similar to the random.choice() variants in Python

IdentifiedFunction.by-id.random_choice.description.2 = \
  Specify a `seed` function argument to make the randomness reproducibly consistent. \
  The `random-seed` RiskScape CLI parameter can also be used to reproducibly change the \
  random number generation, even when a `seed` argument is specified.

IdentifiedFunction.by-id.random_norm.description = \
  Returns a random number from the given normal distribution

IdentifiedFunction.by-id.random_norm.description.1 = \
  The equivalent of this function in Python is: `random.normalvariate(mean, stddev)`

IdentifiedFunction.by-id.random_norm.description.2 = \
  Specify a `seed` function argument to make the randomness reproducibly consistent. \
  The `random-seed` RiskScape CLI parameter can also be used to reproducibly change the \
  random number generation, even when a `seed` argument is specified.

IdentifiedFunction.by-id.random_norm.description.3 = \
  Specifying a `samples` argument will return multiple random numbers as a list.

IdentifiedFunction.by-id.reduce.description = \
  Advanced function for transforming a list in to something else by performing a functional reduction, e.g. \
  `reduce([1, 2, 3], (memo, val) -> memo + val)` \
  performs a sum of elements in the list.

IdentifiedFunction.by-id.relate.description = \
  Implements relate spatial predicate as per \
  https://docs.geoserver.org/stable/en/user/filter/ecql_reference.html#spatial-predicate

IdentifiedFunction.by-id.reproject.description = \
  Reproject a geometry into another coordinate reference system (CRS). E.g to reproject to \
  'EPSG:2193' use `reproject(geom, 'EPSG:2193')`.

IdentifiedFunction.by-id.reproject.description.1 = \
  Alternately the `crs` argument may be another geometry. In this case the input geometry \
  will be reprojected to the CRS that the other geometry is in. \
  E.g `reproject(geom, other_geom)`

IdentifiedFunction.by-id.reproject.description.2 = \
  The `on_failure` option can be used to alter what happens when the geometry cannot be reprojected: \n\
  - ERROR (default), the function will error \n\
  - WARN, a warning is output and null is returned in place of the reprojected geometry \n\
  - IGNORE, null is returned in place of the reprojected geometry, no warnings are output

IdentifiedFunction.by-id.round.description = \
  Rounds a number to the closest integer, or the number of digits (decimal places) specified

IdentifiedFunction.by-id.scale.description = \
  Scales the numeric `input_value` by multiplying it by the `scale_factor` argument. \
  If the `input_value` is a struct it will scale the numeric members of the struct and leave other members untouched.

IdentifiedFunction.by-id.select_attr.description = \
  Returns the subset of attributes that match the given pattern. \
  This is useful when several attributes of interest have a similar naming pattern. \
  See also `get_attr()`, which can be used to return a single exact attribute match.

IdentifiedFunction.by-id.select_attr.description.1 = \
  For example, `select_attr({building_loss: 100, building_damage: 0.1, contents_loss: 50, contents_damage: 0.2}, 'building')` would return `{building_loss=100, building_damage=0.1}`

IdentifiedFunction.by-id.select_attr.description.2 = \
  The pattern argument is a regular expression, so for example `'^building'` will only match attributes \
  that start with 'building', whereas `'building$'` will only match attributes that end with 'building'. \
  Refer to https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html \
  for more information on supported regular expressions.

IdentifiedFunction.by-id.select_attr.description.3 = \
  Advanced users can also rename the attributes using the optional replacements argument. \
  Regular expression capture groups (denoted in brackets) are used to match the part(s) of the attribute \
  name to replace. For example, `select_attr({building_loss: 100, building_count: 2}, '(building)', ['total'])` \
  would replace 'building' with 'total' in the struct, and return `{total_loss=100, total_count=2}`. \
  There should be a replacement for each capture group, for example: \
  `select_attr({total_commercial_building_loss: 100, total_residential_building_loss: 200}, '^(total_).*(loss)', ['', 'AAL'])` \
  would return `{commercial_building_AAL=100, residential_building_AAL=200}`

IdentifiedFunction.by-id.sort.description = \
  Sorts the given list items.

IdentifiedFunction.by-id.sort.description.1 = \
  The list must be comparable (e.g text or numeric) or the `by` argument can be used to select \
  a comparable attribute, e.g  `sort(exposures, by: (i) -> i.value)` would sort the exposures \
  by their value.

IdentifiedFunction.by-id.sort.description.2 = \
  Options can be used to further control the sort order \n\
  - `direction`: used to set the sort direction for attributes. \
  `asc`(default) to sort in ascending order, or `desc` to sort in descending order.

IdentifiedFunction.by-id.sum.description = \
  Aggregate function for calculating a sum of all non-null values in a group.  Also works on lists of numbers in a \
  normal expression.

IdentifiedFunction.by-id.stddev.description = \
  Aggregate function for calculating the standard deviation across a group, e.g. `group(stddev(damage), \
  by: region)`.  Can also be used in a normal expression to calculate the median value of numeric items in a list.

IdentifiedFunction.by-id.to_list.description = \
  Aggregate function for combining all grouped elements in to a list.

IdentifiedFunction.by-id.to_list.description.1 = \
  Use with caution on large datasets, as this can lead to slow performance and memory issues.

IdentifiedFunction.by-id.to_list.description.2 = \
  Can also be used in a normal expressions to turn relational data into a list, e.g. \
  `to_list(bookmark('input_data.csv'))`

IdentifiedFunction.by-id.touches.description = \
  Implements touches geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.warning.description = \
  Outputs a warning containing `message` if the `when` condition is true. \
  The `message` is also returned, to help identify the data record(s) that generated the warning. \
  If the `when` condition is false, null is returned and nothing is output.

IdentifiedFunction.by-id.within.description = \
  Implements within geometric function as per \
  https://docs.geoserver.org/latest/en/user/filter/function_reference.html#geometric-functions

IdentifiedFunction.by-id.is_exposed.description = \
  Simple function to check if an element-at-risk is exposed to the hazard. \
  Returns 1 if the `hazard` argument is present (i.e. not null) and 0 if not. \
  Useful as a placeholder function in risk modelling as it accepts any types for exposure, \
  hazard and optional resource.

IdentifiedFunction.by-id.is_not_null.description = \
  Returns true if the given argument is not null, i.e. it contains a value

IdentifiedFunction.by-id.is_nothing.description = \
  Tests whether the given argument is the special 'nothing' type, which means that it is always null.

IdentifiedFunction.by-id.is_nothing.description.1 = \
  The nothing type is typically only returned by built-in RiskScape functions, such as `get_attr()`. \
  Note that `is_null()` tests for a one-off null value (i.e. any one row of data), \
  whereas `is_nothing()` is checking for a constant null value across all rows of data.

IdentifiedFunction.by-id.not.description = \
  Returns the negation of the given input

IdentifiedFunction.by-id.is_point.description = \
  Tests whether a geometry is a point. Returns true for point geometries, false for all other geometry types \
  (including multi-points). Empty point geometries will also return true.

IdentifiedFunction.by-id.is_multipoint.description = \
  Tests whether a geometry is a multi-point. Returns true for multi-point geometries, false for all other geometry types \
  (including single points).

IdentifiedFunction.by-id.is_line.description = \
  Tests whether a geometry is a line geometry. Returns true for both single line and multi-line geometries, \
  false for all other geometry types. Empty line geometries will also return true.

IdentifiedFunction.by-id.is_polygon.description = \
  Tests whether a geometry is a polygon geometry. Returns true for both single polygon and multi-polygon geometries, \
  false for all other geometry types. Empty polygon geometries will also return true.

IdentifiedFunction.by-id.is_multi.description = \
  Tests whether a geometry is a multi-geometry or geometry collection. Returns true for multi-point, \
  multi-line, multi-polygon, and geometry collection types, false for single geometries (point, line, polygon).

