.. _csv_functions:

# CSV function framework

The CSV function framework can be used to easily create hazard functions that
interpolate a curve built from CSV data.

.. tip::
    You can also read the :ref:`functions_tutorial` tutorial for a practical worked
    example of setting up fragility functions using the CSV framework.

Take the following fictitious table of damage ratios for our elements-at-risk:

| Hazard Intensity | DR   |
|------------------|------|
| 0                | 0    |
| 0.2              | 0.01 |
| 0.4              | 0.1  |
| 0.6              | 0.4  |
| 0.8              | 1    |


It plots points along a curve that moves from 0 to 100% damage as the hazard
intensity increases. We can convert this table in to a CSV file which RiskScape can
turn in to a damage function for use in your RiskScape models:

```csv
hazard,dr
0, 0
0.2, 0.01
0.4, 0.1
0.6, 0.4
0.8, 1
```

We add the function to your RiskScape project with a few lines of INI configuration:

```ini
[function damage]
location = damage-curve.csv
```

You can test the function out using the RiskScape `expr` command:

```bash
$ riskscape expr eval "damage(exposure: {}, hazard: 0.25)"
0.03249999999999999
```

.. note::

  The CSV framework always produces functions of the form `id(exposure, hazard)`, even
  if it doesn't use the exposure in its calculations. This is so functions can be
  used easily by wizard models and makes them consistent with the form
  that most RiskScape models will expect them to be in.

## Multiple curves per function

The previous example was fairly simple - it defined a single curve and ignored
any of the exposure layer's attributes.  We can modify our previous example to
consider different types of "horizontal" infrastructure, and return a different
curve for each:

| Hazard Intensity | Road | Electricity | Pipes |
|------------------|------|-------------|-------|
| 0                | 0    | 0           | 0     |
| 0.2              | 0.01 | 0           | 0.1   |
| 0.4              | 0.1  | 0.1         | 0.45  |
| 0.6              | 0.4  | 0.15        | 0.5   |
| 0.8              | 1    | 0.4         | 0.5   |
| 1.0              | 1    | 0.7         | 0.5   |
| 1.2              | 1    | 1           | 0.5   |


Our table now plots three curves, which we can convert in to a CSV as before:

```csv
hazard,road,electricity,pipe
0, 0, 0, 0
0.2, 0.01, 0, 0.1
0.4, 0.1, 0.1, 0.45
0.6, 0.4, 0.15, 0.5
0.8, 1, 0.4, 0.5
1.0, 1, 0.7, 0.5
1.2, 1, 1, 0.5
```

To use this CSV correctly, we need to tell our function which attribute in
our exposure layer defines the type of horizontal infrastructure, for example:

```
[function infrastructure_damage]
location = damage-curves.csv
# Tell RiskScape to use this attribute to pick a curve
exposure-attribute = infrastructure_type
# Which column to use if none matches
default-exposure-value = road
```

Try running the expression example from before, but add an `infrastructure_type`
attribute to our exposure layer:

```
riskscape expr eval "road_hazard(exposure: {infrastructure_type: 'pipe'}, hazard: 0.25)"
```

You'll get a different result as you change the value of `infrastructure_type`,
reflecting the different curve that was used for the damage function.

## Returning multiple values

A more complicated example involves removing the `exposure-attribute` parameter
from the `[function infrastructure_damage]` configuration.  The function will now
return three values from the three different curves, instead of picking one based on
the exposure layer.  This can be useful for returning parameters to a normal curve,
or other, more advanced, cases.

## Configuration Reference

### `location`

The location of the CSV file to use in the function.

### `hazard-column`

Default: `hazard`

The column in the CSV file that contains the hazard intensity.

### `return-column`

Default: all numeric columns from the CSV (excluding the `hazard-column`)

Add a `return-column` entry for each column that you want to have returned.

If only one column is returned then a single numeric value will be returned.

If multiple columns are returned then the result will be a struct with an attribute
named for each column.

### `exposure-attribute`

Uses an attribute from the exposure layer to select which curve to use, for example:

```ini
[function hazard_by_exposure_type]
location = ./hazard-dr.csv
exposure-attribute = type
default-exposure-value = road
```

### `default-exposure-value`

Sets the CSV column to use when there is no column that matches the `exposure-attribute`.

Required when `exposure-attribute` is defined.

### `map-value`

A more advanced parameter that allows supplying an expression that can transform the
value from the curve.

This example shows how it can be used to sample from a log-normal curve to give the
probability of an element-at-risk being in a particular damage state.

```ini
[function sample_damage_state]
location = damage-state.csv
# NB value 'wraps' the different returned values in the case your
# CSV has multiple columns
map-value = lognorm_cdf(hazard, value.mean, value.stdev)
```

.. note::

  ``map-value`` is applied after ``exposure-attribute`` (when defined), meaning ``value``
  will be a single floating-point number, rather than a struct with attributes for
  each column from the CSV.

