---
title: "lczexplore_en"
author: "Matthieu Gousseff"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
resource_files:
  - vignettes/Redon.png
vignette: >
    %\VignetteIndexEntry{lczexplore_en}
    %\VignetteEngine{knitr::rmarkdown}
    %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
        collapse = TRUE,
        comment = "#>"
)
```


# A package to explore Local Climate Zones: lczexplore
## Purpose and origin
The lczexplore package was developed thanks to the PAENDORA2 (Pour la gestion du confort estival : Données, Outils et Recherche-Action, 2022 -2025, funded by ADEME, a French agency for ecological transition).

Its purpose is to easily compare different Local Climate Zone (LCZ) classifications on the same study territory.

Before using this package, one must assign a local climate zone (LCZ) type 
to each Spatial Reference Units of a territory.
These units can be topological units or geometries derived from pixels of a raster approach 
the package deals with the conversion). Fo a detailed example of the raster approach, 
please read the "lczexplore_raster_vector" vignette (`vignette("lczexplore_raster_vector"`).
As several workflows can produce these LCZ types, this package allows to represent them and to compare 
pairs of these classifications (pairwise).
It has been extended to compare any pair of qualitative variable set on valid geographical units. 


## Installation

The following allows the installation from the github repository: (`devtools::install_github("orbisgis/lczexplore", build_vignettes = TRUE)`).

On can also install from the tar.gz file and install it (see `?install.packages`).


Load the package: `library(lczexplore)`.
```{r, load, eval = TRUE, echo = TRUE}
library(ggplot2)
library(lczexplore)
```

# First use-case: load a file with geometries and standard LCZ

## Import files with importLCZvect function

The function `importLCZvect` is the generic import function for the file containing geometries, 
or Reference Spatial Units (RSU), and the associated Local Climate Zone Type (LCZ). 
Imports of .fgb (prefered), .geojson and .shp files were tested, but any format accepted by the function `st_read`
of the `sf` package should work.

The `dirPath` and the `file` arguments set the path to the folder and the filename to be loaded. 
The compulsory argument  `column` is the name of the column in which are the LCZ types.
The optional arguments `geomID` and `confid` allow the user to load column of geometry identifiers 
and a column containing a measure of the confidence associated to the LCZ type of a given geometry 
(these are needed for the sensitivity analysis described below). 

The default output of `importLCZvect` is an object of class `simple feature` 
as defined by the openGIS consortium and as handled by the `sf` package, an R reference 
library for Geographical Information System vector Data [https://doi.org/10.32614/RJ-2018-009].

If one sets the argument `output="bBox"`, importLCZvect will output only the bounding 
box of the geometries of the input file. It is useful, for instance, when you want to use it to 
crop another file and study the same area.


```{r, load-files, eval = TRUE, echo = TRUE}
dirPath <- system.file("extdata/multipleWfs/Redon", package = "lczexplore")
redonOSM <- importLCZvect(dirPath = dirPath, file = "osm_lcz.fgb", column = "LCZ_PRIMARY")
redonBDT <- importLCZvect(dirPath = dirPath, file = "bdt_lcz.fgb", column = "LCZ_PRIMARY")
#
```
## Map the LCZ types with the function showLCZ

Once the dataset has been loaded into an R object of class `sf`, the function `showLCZ` 
produces the map of it's repartition. The argument`sf` sets the input dataset, 
the column of the LCZ types is passed to the argument `column`. The argument `wf` is simply a string  
to specify which workflow produced the input data (it is used to produce the title).

## Standard representation

For standard LCZ types, one sets the argument `repr="standard"`, and the function will recognize 
levels from 1 to 10 and from 101 to 107. 
It is the recommended choice. But `standard` representation will also accept levels from 11 to 17 and from A to G.
(for other conventions, see the `alter` representation).


```{r, show, fig.dim = c(8, 6), eval = TRUE, echo = TRUE}
showLCZ(sf = redonOSM, wf = "OSM", column = "LCZ_PRIMARY", repr = "standard", LCZlevels = "", colors = "")
```
One can note that by default, all the 17 possible types of an LCZ classification are present in the legend. This makes comparison easier when one compares dataset with different present levels. 
To only represent the present levels, set `drop=TRUE`.

```{r, show-with-drop, fig.dim = c(8, 6), echo = FALSE, eval = TRUE}
showLCZ(sf = redonOSM, wf = "OSM", column = "LCZ_PRIMARY", repr = "standard", drop = TRUE)
```
### Alternative visualization

The non-standard representation, triggered with `repr=alter` is useful when: 
- one wants to **regroup** some LCZ types into more general categories,
- the LCZ **don't have a standard encoding**
- one want's to use **custom colors**
- one wants to plot... something different from LCZ

With `repr=alter`, one passes the vector of possible levels to the argument `LCZlevels` and the vector of associated colors to the argument `colors`.

If no vector of levels or no vector of colors is given, the levels will be deduced from the unique values present in the data, and the colors will be picked from the "Polychrome 36" palette of the `grDevices` package.

For instance: one can first plot the column without knowing the LCZ levels present.
```{r, show-alter-drop, fig.dim = c(8, 6),  eval = TRUE, echo = TRUE}
# Choice of random colors from a palette
testCol <- palette.colors(n = 17, palette = "Polychrome 36")
showLCZ(sf = redonOSM, wf = "OSM", column = "LCZ_PRIMARY", repr = "alter", colors = testCol, useStandCol = FALSE, drop = TRUE)

```


The colors one wants to use can be specified either by their name (if a known color name in R) or it's RGB code, and passed to the argument `colors`.

```{r, show-chosen-colors, fig.dim = c(8, 6), eval = TRUE, echo = TRUE}

LCZlevels <- c(2, 3, 5, 6, 8, 9, 101, 102, 104, 105, 107)
couleurs <- c("red", "brown1", "orange", "coral", "grey", "darkgreen", "chartreuse4", "springgreen3",
              "darkolivegreen", "black", "#6d67fd")
showLCZ(sf = redonOSM, wf = "OSM", column = "LCZ_PRIMARY", repr = "alter", drop = TRUE, LCZlevels = LCZlevels, colors = couleurs)

```

## Group several LCZ types in a category using groupLCZ

For instance, one may want to illustrate the contour of a city, by grouping the urban LCZs and the vegetation ones.   
Use the `groupLCZ` function and set the dataset with the argument `sf` and the column with `column`. 
Then pass as many vectors as there are grouped category, each of them containing the levels to be grouped together. 
The newly created categories will be stored in the `outCol` column. 
If the user doesn't enter them (by default `outCol="grouped"`).

The newly created dataset can be mapped with `showLCZ` function.

```{r, group-and-show, fig.dim = c(8, 6), eval = TRUE, echo = TRUE}
redonOSMgrouped <- groupLCZ(redonOSM, column = "LCZ_PRIMARY",
                            urban = c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                            industry = "10",
                            vegetation = c("101", "102", "103", "104"),
                            impervious = "105", pervious = "106", water = "107", colors = c("red", "black", "green", "grey", "burlywood", "blue"))
showLCZ(redonOSMgrouped, column = "grouped", repr = "alter", wf = "OSM",
        LCZlevels = c("urban", "industry", "vegetation", "impervious", "pervious", "water"),
        colors = c("red", "black", "green", "grey", "burlywood", "blue"))

```

# Compare two LCZ classification with the function compareLCZ

**The purpose of this package is to easily compare local climate zone classifications produced by different algorithms on the same study area.**
In our example, the GeoClimate workflow was used with two different input data to produce two LCZ classifications: 
the BD TOPO® v2.2, produced by the French National Institute of Geographic and Forest Information, and OpenStreetMap. 

NOTE: The vignette "lczexplore_raster_vector" explores in detail another example with WUDAPT raster data. 


One has to call `compareLCZ` and feed it, for each dataset, 
at least the name of the `sf` object and the name of the `columns` where the LCZ types are stored. 
As the two input data set can have different coordinate reference system (CRS), 
you need to tell which dataset is the reference 
(by default `ref=1`, that is the second data set will be re-transformed into the CRS of the first data set). 

- A map of each LCZ classification is plotted.  
- The function then intersects the geometries of both sf objects in order to get geometries where the **two classification either totally agree either totally disagree.** This agreement is plotted on a third graphics.  
- At last, a confusion matrix (or agreement matrix) is computed: 
the area of each intersected geometry and the values of the two LCZ classifications
are used to show how one type of the first classification breaks up into the levels of the second classification. 
- The matrix is shown in the fourth and last graphics.

NOTE: if the two data sets to compare have the same column names,
the compareLCZ function will concatenate a ".1" string to the column names of the second file

*The graphical output includes 4 graphs and is easier to read after zooming or exporting.*

```{r, compare, fig.dim = c(12,9 ), echo = TRUE, fig.show="hide"}

path <- system.file('extdata/redonCompare',package="lczexplore")
redonCompare <- compareLCZ(sf1 = redonBDT, wf1 = "bdt", geomID1 = "ID_RSU", column1 = "LCZ_PRIMARY",
                           confid1 = "LCZ_UNIQUENESS_VALUE",
                           sf2 = redonOSM, wf2 = "osm", geomID2 = "ID_RSU", column2 = "LCZ_PRIMARY",
                           confid2 = "LCZ_UNIQUENESS_VALUE", exwrite = FALSE, saveG = path)
```

```{r, import-compare-plot-prettier, out.width = "680px"}

path <- system.file('extdata/GeneralUniquenessSensib.png',package="lczexplore")
knitr::include_graphics(path, error=FALSE)

```

The comparison also works on grouped data. 
```{r, compare-grouped, echo = TRUE, fig.show="hide" }
redonOSMgrouped <- groupLCZ(redonOSM, column = "LCZ_PRIMARY",
                            urban = c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                            industry = "10",
                            vegetation = c("101", "102", "103", "104"),
                            impervious = "105", pervious = "106", water = "107", colors = c("red", "black", "green", "grey", "burlywood", "blue"))
redonBDTgrouped <- groupLCZ(redonBDT, column = "LCZ_PRIMARY",
                            urban = c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                            industry = "10",
                            vegetation = c("101", "102", "103", "104"),
                            impervious = "105", pervious = "106", water = "107", colors = c("red", "black", "green", "grey", "burlywood", "blue"))
path <- paste0(system.file("extdata/", package = "lczexplore"), "/groupedComparison")
comparisonGrouped <- compareLCZ(sf1 = redonOSMgrouped, column1 = "grouped",
                                sf2 = redonBDTgrouped, column2 = "grouped",
                                repr = "alter",
                                levels = c("urban", "industry", "vegetation", "impervious", "pervious", "water"),
                                colors = c("red", "black", "green", "grey", "burlywood", "blue"), saveG = path)
```

```{r, compare-grouped-plot-prettier, out.width = "680px"}
path <- paste0(system.file("extdata/", package = "lczexplore"), "/groupedComparison.png")
knitr::include_graphics(path, error=FALSE)

```

A little cheat is possible ! You can try to group and compare on-the-fly with `tryGroup=TRUE`. The syntax is then as shown in the nex code chunk. 

```{r, compare-on-the-fly, out.width="70%", echo = TRUE, fig.show="hide"}
comparisonGrouped <- compareLCZ(sf1 = redonBDT, column1 = "LCZ_PRIMARY", wf1 = "groupedBDT",
                                sf2 = redonOSM, column2 = "LCZ_PRIMARY", wf2 = "groupedOSM",
                                repr = "alter", ref = 2, saveG = "", exwrite = FALSE, location = "Redon", plot = TRUE,
                                urban = c("1", "2", "3", "4", "5", "6", "7", "8", "9"),
                                industry = "10",
                                vegetation = c("101", "102", "103", "104"),
                                impervious = "105", pervious = "106", water = "107",
                                colors = c("red", "black", "green", "grey", "burlywood", "blue"), tryGroup = TRUE)


```


## Output data for further analysis

`CompareLCZ `outputs a list called `matConfOut` which contains:

- `$data` the intersected geometries, their identifiers (if `geomID` was not empty), their LCZ types and their areas,
- `$matConfLarge` the confusion matrix,
- `$percAgg` the general agreement of the two classifications on the whole area (as a percentage of the global surface of the area),
- `$areas` the summed area for each LCZ of both classifications. 


At last: it `exWrite=TRUE` the data are exported to a .csv file whose name 
is created from the argument `wf1` and `wf2`. It can then be loaded for further analysis.  

```{r, values}
comparisonGrouped$percAgg
comparisonGrouped$areas
```


# Sensitivity of the agreement to the confidence value

Some algorithm may provide a **confidence value** associated to the LCZ type.
For instance, GeoClimate, for a given geometry, chooses the LCZ type according to a 
distance to a hypercube defining each LCZ type (in a space defined by the urban canopy parameters)?. 
Therefore, GeoClimate assigns the geometry to the closest type, but another type may have been quite close too. 
GeoClimate supplies a **uniqueness value**, between 0 and 1. The closer it is to 1, the less the second 
LCZ type was a good candidate. So this uniqueness can be seen as a confidence value.


## Import the necessary data: LCZ type, but also confidence.

When using the `importLCZvect` function one needs to specify the confidence value associated 
to the LCZ (`confid` argument). On can also set the name of the geometry identifier (`geomID` argument ).

```{r, compare-for-sensitivity}
dirPath <- system.file("extdata/multipleWfs/Redon", package = "lczexplore")

redonOSM <- importLCZvect(dirPath = dirPath, file = "osm_lcz.fgb", column = "LCZ_PRIMARY", geomID = "ID_RSU", confid = "LCZ_UNIQUENESS_VALUE")

redonBDT <- importLCZvect(dirPath = dirPath, file = "bdt_lcz.fgb", column = "LCZ_PRIMARY", geomID = "ID_RSU", confid = "LCZ_UNIQUENESS_VALUE")

redonCompare <- compareLCZ(sf1 = redonBDT, wf1 = "bdt", geomID1 = "ID_RSU", column1 = "LCZ_PRIMARY",
                           confid1 = "LCZ_UNIQUENESS_VALUE",
                           sf2 = redonOSM, wf2 = "osm", geomID2 = "ID_RSU", column2 = "LCZ_PRIMARY", confid2 = "LCZ_UNIQUENESS_VALUE",
                           exwrite = FALSE, plot = FALSE)
```


The function `confidSensib` performs the sensitivity analysis from the output of `compareLCZ`.

NOTE: if the two data sets to compare have the same column names, 
the compareLCZ function will concatenate a ".1" string to the column names of the second file, 
so the enriched names will be the ones to feed `confidSensib`.

The question we want to answer is: **Does the agreement between the two classification gets bigger if we keep only the geometries for which the LCZ value is associated to a confidence value bigger than a thershold?**

The span of the confidence values is divided on as many points as the user chooses with the argument `nPoints`

For each of these thresholds, the function only keeps the reference spatial units (RSU, i.e. the geometries) for which the confidence value is higher than the threshold. Then it computes the agreement between the classifications based on these geoms.

```{r, perform-sensitivity, fig.show="hide"}
names(redonCompare$data)
confidRedon <- confidSensib(inputDf = redonCompare$data, filePath = "", nPoints = 10,
                            wf1 = "bdtopo_2_2", wf2 = "osm",
                            geomID1 = "ID_RSU", column1 = "bdt", confid1 = "LCZ_UNIQUENESS_VALUE",
                            geomID2 = "ID_RSU.1", column2 = "osm", confid2 = "LCZ_UNIQUENESS_VALUE.1",
                            sep = ";", repr = "standard",
                            plot = TRUE, saveG = system.file("extdata/", package = "lczexplore"))

```
```{r, show-sensitivity-prettier, out.width = "680px"}
path <- paste0(system.file("extdata/GeneralUniquenessSensib",package="lczexplore"), ".png")
knitr::include_graphics(path, error=FALSE)
```

```{R, cleaningpng}
file.remove(path)
```

One can see that the agreement between classifications using BDTOPO and OpenStreetMap tends to increase when the confidence of the LCZ we keep increases (except for the open low LCZ !).

```{r, sensitivity-by-LCZ-type, out.width = "680px"}

knitr::include_graphics("byLCZUniquenessSensib.png", error=FALSE)

```

These are the main functions of the package, for further use, refer to the man page of each function.

```{r cleanup}
if (file.exists("byLCZUniquenessSensib.png")){file.remove("byLCZUniquenessSensib.png")}
if (file.exists("GeneralUniquenessSensib.png")){file.remove("GeneralUniquenessSensib.png")}
if (file.exists("comparison.png")){file.remove("comparison.png")}

```