diff --git a/plotting/color_manager.R b/plotting/color_manager.R
new file mode 100644
index 0000000000000000000000000000000000000000..bb3c728d99bef6caea8889cdc6c5d16235419987
--- /dev/null
+++ b/plotting/color_manager.R
@@ -0,0 +1,194 @@
+# \\\
+# Copyright 2021-2022 Louis Héraut*1
+#
+# *1   INRAE, France
+#      louis.heraut@inrae.fr
+#
+# This file is part of ash R toolbox.
+#
+# ash R toolbox is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# ash R toolbox is distributed in the hope that it will be useful, but 
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ash R toolbox.  If not, see <https://www.gnu.org/licenses/>.
+# ///
+#
+#
+# color_manager.R
+
+
+### 1. COLOR ON COLORBAR _____________________________________________
+# Returns a color of a palette corresponding to a value included
+# between the min and the max of the variable
+get_color = function (value, min, max, ncolor=256, palette_name='perso', reverse=FALSE) {
+
+    # If the value is a NA return NA color
+    if (is.na(value)) {
+        return (NA)
+    }
+    
+    # If the palette chosen is the personal ones
+    if (palette_name == 'perso') {
+        colorList = palette_perso
+    # Else takes the palette corresponding to the name given
+    } else {
+        colorList = brewer.pal(11, palette_name)
+    }
+    
+    # Gets the number of discrete colors in the palette
+    nSample = length(colorList)
+    # Recreates a continuous color palette
+    palette = colorRampPalette(colorList)(ncolor)
+    # Separates it in the middle to have a cold and a hot palette
+    Sample_hot = 1:(as.integer(nSample/2)+1)
+    Sample_cold = (as.integer(nSample/2)+1):nSample
+    palette_hot = colorRampPalette(colorList[Sample_hot])(ncolor)
+    palette_cold = colorRampPalette(colorList[Sample_cold])(ncolor)
+
+    # Reverses the palette if it needs to be
+    if (reverse) {
+        palette = rev(palette)
+        palette_hot = rev(palette_hot)
+        palette_cold = rev(palette_cold)
+    }
+
+    # Computes the absolute max
+    maxAbs = max(abs(max), abs(min))
+
+    # If the value is negative
+    if (value < 0) {
+        # Gets the relative position of the value in respect
+        # to its span
+        idNorm = (value + maxAbs) / maxAbs
+        # The index corresponding
+        id = round(idNorm*(ncolor - 1) + 1, 0)
+        # The associated color
+        color = palette_cold[id]
+    # Same if it is a positive value
+    } else {
+        idNorm = value / maxAbs
+        id = round(idNorm*(ncolor - 1) + 1, 0)
+        color = palette_hot[id]
+    }
+    return(color)
+}
+
+## 2. COLORBAR _______________________________________________________
+# Returns the colorbar but also positions, labels and colors of some
+# ticks along it 
+get_palette = function (min, max, ncolor=256, palette_name='perso', reverse=FALSE, nbTick=10) {
+    
+    # If the palette chosen is the personal ones
+    if (palette_name == 'perso') {
+        colorList = palette_perso
+    # Else takes the palette corresponding to the name given
+    } else {
+        colorList = brewer.pal(11, palette_name)
+    }
+    
+    # Gets the number of discrete colors in the palette
+    nSample = length(colorList)
+    # Recreates a continuous color palette
+    palette = colorRampPalette(colorList)(ncolor)
+    # Separates it in the middle to have a cold and a hot palette
+    Sample_hot = 1:(as.integer(nSample/2)+1)
+    Sample_cold = (as.integer(nSample/2)+1):nSample
+    palette_hot = colorRampPalette(colorList[Sample_hot])(ncolor)
+    palette_cold = colorRampPalette(colorList[Sample_cold])(ncolor)
+
+    # Reverses the palette if it needs to be
+    if (reverse) {
+        palette = rev(palette)
+        palette_hot = rev(palette_hot)
+        palette_cold = rev(palette_cold)
+    }
+
+    # If the min and the max are below zero
+    if (min < 0 & max < 0) {
+        # The palette show is only the cold one
+        paletteShow = palette_cold
+    # If the min and the max are above zero
+    } else if (min > 0 & max > 0) {
+        # The palette show is only the hot one
+        paletteShow = palette_hot
+    # Else it is the entire palette that is shown
+    } else {
+        paletteShow = palette
+    }
+
+    # The position of ticks is between 0 and 1
+    posTick = seq(0, 1, length.out=nbTick)
+    # Blank vector to store corresponding labels and colors
+    labTick = c()
+    colTick = c()
+    # For each tick
+    for (i in 1:nbTick) {
+        # Computes the graduation between the min and max
+        lab = (i-1)/(nbTick-1) * (max - min) + min
+        # Gets the associated color
+        col = get_color(lab, min=min, max=max,
+                        ncolor=ncolor,
+                        palette_name=palette_name,
+                        reverse=reverse)
+        # Stores them
+        labTick = c(labTick, lab)
+        colTick = c(colTick, col)
+    }
+    # List of results
+    res = list(palette=paletteShow, posTick=posTick,
+               labTick=labTick, colTick=colTick)
+    return(res)
+}
+
+## 3. PALETTE TESTER _________________________________________________
+# Allows to display the current personal palette
+palette_tester = function (palette_name='perso', n=256) {
+
+    # If the palette chosen is the personal ones
+    if (palette_name == 'perso') {
+        colorList = palette_perso
+    # Else takes the palette corresponding to the name given
+    } else {
+        colorList = brewer.pal(11, palette_name)
+    }
+    
+    # An arbitrary x vector
+    X = 1:n
+    # All the same arbitrary y position to create a colorbar
+    Y = rep(0, times=n)
+
+    # Recreates a continuous color palette
+    palette = colorRampPalette(palette_perso)(n)
+
+    # Open a plot
+    p = ggplot() + 
+        # Make the theme blank
+        theme(
+            plot.background = element_blank(), 
+            panel.grid.major = element_blank(),
+            panel.grid.minor = element_blank(), 
+            panel.border = element_blank(),
+            panel.background = element_blank(),
+            axis.title.x = element_blank(),
+            axis.title.y = element_blank(),
+            axis.text.x = element_blank(), 
+            axis.text.y = element_blank(),
+            axis.ticks = element_blank(),
+            axis.line = element_blank()
+        ) +
+        # Plot the palette
+        geom_line(aes(x=X, y=Y), color=palette[X], size=60) +
+        scale_y_continuous(expand=c(0, 0))
+
+    # Saves the plot
+    ggsave(plot=p,
+           filename=paste('palette_test', '.pdf', sep=''),
+           width=10, height=10, units='cm', dpi=100)
+}
diff --git a/plotting/shortcut.R b/plotting/shortcut.R
new file mode 100644
index 0000000000000000000000000000000000000000..2b18663ca013e8602827de96f9db68ec8a6eeded
--- /dev/null
+++ b/plotting/shortcut.R
@@ -0,0 +1,185 @@
+# \\\
+# Copyright 2021-2022 Louis Héraut*1
+#
+# *1   INRAE, France
+#      louis.heraut@inrae.fr
+#
+# This file is part of ash R toolbox.
+#
+# ash R toolbox is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# ash R toolbox is distributed in the hope that it will be useful, but 
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ash R toolbox.  If not, see <https://www.gnu.org/licenses/>.
+# ///
+#
+#
+# shortcut.R
+
+
+short_nPeriodMax = function (list_df2plot, Code) {
+    # Gets a trend example
+    df_trend = list_df2plot[[1]]$trend
+
+    # Convert 'trend_period' to list
+    trend_period = as.list(trend_period)
+    # Number of trend period
+    nPeriod_trend = length(trend_period)
+    
+    # Fix the maximal number of period to the minimal possible
+    nPeriodMax = 0
+    # For all code 
+    for (code in Code) {
+        # Extracts the trend corresponding to the code
+        df_trend_code = df_trend[df_trend$code == code,]
+        
+        # Extract start and end of trend periods
+        Start = df_trend_code$period_start
+        End = df_trend_code$period_end
+        # Get the name of the different period
+        UStart = levels(factor(Start))        
+        UEnd = levels(factor(End))
+
+        # Compute the max of different start and end
+        # so the number of different period
+        nPeriod = max(length(UStart), length(UEnd))
+
+        # If the number of period for the trend is greater
+        # than the current max period, stocks it
+        if (nPeriod > nPeriodMax) {
+            nPeriodMax = nPeriod
+        }
+    }
+    
+    res = list(npt=nPeriod_trend, npM=nPeriodMax) 
+    return (res)
+}
+
+short_tab = function (list_df2plot, Code, nbp, nCode, nPeriod_max) {
+    # Blank array to store time info
+    tab_Start =  array(rep('', nCode*nbp*nPeriod_max),
+                       dim=c(nCode, nbp, nPeriod_max))
+    tab_End = array(rep('', nCode*nbp*nPeriod_max),
+                    dim=c(nCode, nbp, nPeriod_max))
+    
+    # For all code
+    for (k in 1:nCode) {
+        # Gets the code
+        code = Code[k]
+        # For all the variable
+        for (i in 1:nbp) {
+            df_trend = list_df2plot[[i]]$trend
+            # Extracts the trend corresponding to the code
+            df_trend_code = df_trend[df_trend$code == code,]
+            
+            # Extract start and end of trend periods
+            Start = df_trend_code$period_start
+            End = df_trend_code$period_end
+            # Get the name of the different period
+            UStart = levels(factor(Start))        
+            UEnd = levels(factor(End))
+            
+            # Compute the max of different start and end
+            # so the number of different period
+            nPeriod = max(length(UStart), length(UEnd))
+
+            # For all the period
+            for (j in 1:nPeriod_max) {
+                # Saves the time info
+                tab_Start[k, i, j] = as.character(Start[j])
+                tab_End[k, i, j] = as.character(End[j])                
+            }
+        }
+    }
+    res = list(start=tab_Start, end=tab_End)
+    return (res)
+}
+
+short_trendExtremes = function (list_df2plot, tab_Start, tab_End, Code, nPeriod_trend, nbp, nCode, nPeriod_max) {
+    
+    # Blank array to store mean of the trend for each
+    # station, perdiod and variable
+    TrendValue_code = array(rep(1, nPeriod_trend*nbp*nCode),
+                            dim=c(nPeriod_trend, nbp, nCode))
+
+    # For all the period
+    for (j in 1:nPeriod_max) {
+        # For all the code
+        for (k in 1:nCode) {
+            # Gets the code
+            code = Code[k]
+            
+            for (i in 1:nbp) {
+                # Extracts the data corresponding to the
+                # current variable
+                df_data = list_df2plot[[i]]$data
+                # Extracts the trend corresponding to the
+                # current variable
+                df_trend = list_df2plot[[i]]$trend
+                # Extracts the type of the variable
+                type = list_df2plot[[i]]$type
+                alpha = list_df2plot[[i]]$alpha
+                # Extracts the data corresponding to the code
+                df_data_code = df_data[df_data$code == code,] 
+                df_trend_code = df_trend[df_trend$code == code,]
+
+                # Gets the associated time info
+                Start = tab_Start[k, i, j]
+                End = tab_End[k, i, j]
+                
+                # Extracts the corresponding data for the period
+                df_data_code_per =
+                    df_data_code[df_data_code$Date >= Start 
+                                 & df_data_code$Date <= End,]
+                
+                # Same for trend
+                df_trend_code_per = 
+                    df_trend_code[df_trend_code$period_start == Start 
+                                  & df_trend_code$period_end == End,]
+                
+                # Computes the number of trend analysis selected
+                Ntrend = nrow(df_trend_code_per)
+                # If there is more than one trend on the same period
+                if (Ntrend > 1) {
+                    # Takes only the first because they are similar
+                    df_trend_code_per = df_trend_code_per[1,]
+                }
+
+                # If it is a flow variable
+                if (type == 'sévérité') {
+                    # Computes the mean of the data on the period
+                    dataMean = mean(df_data_code_per$Value, na.rm=TRUE)
+                    # Normalises the trend value by the mean of the data
+                    trendValue = df_trend_code_per$trend / dataMean
+                    # If it is a date variable
+                } else if (type == 'saisonnalité') {
+                    trendValue = df_trend_code_per$trend
+                }
+                
+                # If the p value is under the threshold
+                if (df_trend_code_per$p <= alpha) {
+                    # Stores the mean trend
+                    TrendValue_code[j, i, k] = trendValue
+                    # Otherwise
+                } else {
+                    # Do not stocks it
+                    TrendValue_code[j, i, k] = NA
+                }                
+            }
+        }
+    }
+
+    # Compute the min and the max of the mean trend for all the station
+    minTrendValue = apply(TrendValue_code, c(1, 2), min, na.rm=TRUE)
+    maxTrendValue = apply(TrendValue_code, c(1, 2), max, na.rm=TRUE)
+
+    res = list(min=minTrendValue, max=maxTrendValue)
+    return (res)
+}
diff --git a/plotting/tools.R b/plotting/tools.R
new file mode 100644
index 0000000000000000000000000000000000000000..81f881ac28a8b1f08aeb82d16906896575f1f82b
--- /dev/null
+++ b/plotting/tools.R
@@ -0,0 +1,103 @@
+# \\\
+# Copyright 2021-2022 Louis Héraut*1
+#
+# *1   INRAE, France
+#      louis.heraut@inrae.fr
+#
+# This file is part of ash R toolbox.
+#
+# ash R toolbox is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# ash R toolbox is distributed in the hope that it will be useful, but 
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with ash R toolbox.  If not, see <https://www.gnu.org/licenses/>.
+# ///
+#
+#
+# tools.R
+
+
+
+
+### 2.3. Circle ______________________________________________________
+# Allow to draw circle in ggplot2 with a radius and a center position
+gg_circle = function(r, xc, yc, color="black", fill=NA, ...) {
+    x = xc + r*cos(seq(0, pi, length.out=100))
+    ymax = yc + r*sin(seq(0, pi, length.out=100))
+    ymin = yc + r*sin(seq(0, -pi, length.out=100))
+    annotate("ribbon", x=x, ymin=ymin, ymax=ymax, color=color,
+             fill=fill, ...)
+}
+
+## 6. OTHER TOOLS ____________________________________________________
+### 6.1. Number formatting ___________________________________________
+# Returns the power of ten of the scientific expression of a value
+get_power = function (value) {
+
+    # Do not care about the sign
+    value = abs(value)
+    
+    # If the value is greater than one
+    if (value >= 1) {
+        # The magnitude is the number of character of integer part
+        # of the value minus one
+        power = nchar(as.character(as.integer(value))) - 1
+    # If value is zero
+    } else if (value == 0) {
+        # The power is zero
+        power = 0
+    # If the value is less than one
+    } else {
+        # Extract the decimal part
+        dec = gsub('0.', '', as.character(value), fixed=TRUE)
+        # Number of decimal with zero
+        ndec = nchar(dec)
+        # Number of decimal without zero
+        nnum = nchar(as.character(as.numeric(dec)))
+        # Compute the power of ten associated
+        power = -(ndec - nnum + 1)
+    }
+    return(power)
+}
+
+### 6.2. Pourcentage of variable _____________________________________
+# Returns the value corresponding of a certain percentage of a
+# data serie
+gpct = function (pct, L, min_lim=NULL, shift=FALSE) {
+
+    # If no reference for the serie is given
+    if (is.null(min_lim)) {
+        # The minimum of the serie is computed
+        minL = min(L, na.rm=TRUE)
+    # If a reference is specified
+    } else {
+        # The reference is the minimum
+        minL = min_lim
+    }
+
+    # Gets the max
+    maxL = max(L, na.rm=TRUE)
+    # And the span
+    spanL = maxL - minL
+    # Computes the value corresponding to the percentage
+    xL = pct/100 * as.numeric(spanL)
+
+    # If the value needs to be shift by its reference
+    if (shift) {
+        xL = xL + minL
+    }
+    return (xL)
+}
+
+### 6.3. Add months __________________________________________________
+add_months = function (date, n) {
+    new_date = seq(date, by = paste (n, "months"), length = 2)[2]
+    return (new_date)
+}