From 01ce7c2c67574775c62d43420a60283cccdb92e1 Mon Sep 17 00:00:00 2001
From: gmillot <gael.millot@pasteur.fr>
Date: Fri, 11 Mar 2022 19:13:28 +0100
Subject: [PATCH] release v11.2.0: fun_open() improved for parallelization

---
 README.md                    |    10 +
 cute_little_R_functions.R    | 26675 +++++++++++++++++----------------
 cute_little_R_functions.docx |   Bin 498725 -> 499273 bytes
 3 files changed, 13352 insertions(+), 13333 deletions(-)

diff --git a/README.md b/README.md
index ee9f747..f8e35bb 100755
--- a/README.md
+++ b/README.md
@@ -170,6 +170,16 @@ Gitlab developers
 
 ## WHAT'S NEW IN
 
+### v11.2.0
+
+1) fun_open() improved for parallelization
+
+
+### v11.1.0
+
+1) bug removed in fun_gg_boxplot when having a single color in dot.plot argument
+
+
 ### v11.0.0
 
 1) fun_slide() debugged and fun_test() improved
diff --git a/cute_little_R_functions.R b/cute_little_R_functions.R
index 69ee7f0..e270834 100755
--- a/cute_little_R_functions.R
+++ b/cute_little_R_functions.R
@@ -98,343 +98,343 @@
 # -> transferred into the cute package
 # Do not modify this function in cute_little_R_function anymore. See the cute repo
 fun_check <- function(
-    data, 
-    class = NULL, 
-    typeof = NULL, 
-    mode = NULL, 
-    length = NULL, 
-    prop = FALSE, 
-    double.as.integer.allowed = FALSE, 
-    options = NULL, 
-    all.options.in.data = FALSE, 
-    na.contain = FALSE, 
-    neg.values = TRUE, 
-    print = FALSE, 
-    data.name = NULL, 
-    fun.name = NULL
+data, 
+class = NULL, 
+typeof = NULL, 
+mode = NULL, 
+length = NULL, 
+prop = FALSE, 
+double.as.integer.allowed = FALSE, 
+options = NULL, 
+all.options.in.data = FALSE, 
+na.contain = FALSE, 
+neg.values = TRUE, 
+print = FALSE, 
+data.name = NULL, 
+fun.name = NULL
 ){
-    # AIM
-    # Check the class, type, mode and length of the data argument
-    # Mainly used to check the arguments of other functions
-    # Check also other kind of data parameters, is it a proportion? Is it type double but numbers without decimal part?
-    # If options == NULL, then at least class or type or mode or length argument must be non-null
-    # If options is non-null, then class, type and mode must be NULL, and length can be NULL or specified
-    # WARNINGS
-    # The function tests what is written in its arguments, even if what is written is incoherent. For instance, fun_check(data = factor(1), class = "factor", mode = "character") will return a problem, whatever the object tested in the data argument, because no object can be class "factor" and mode "character" (factors are class "factor" and mode "numeric"). Of note, length of object of class "environment" is always 0
-    # If the tested object is NULL, then the function will always return a checking problem
-    # Since R >= 4.0.0, class(matrix()) returns "matrix" "array", and not "matrix" alone as before. However, use argument class = "matrix" to check for matrix object (of class "matrix" "array" in R >= 4.0.0) and use argument class = "array" to check for array object (of class "array" in R >= 4.0.0)
-    # ARGUMENTS
-    # data: object to test
-    # class: character string. Either one of the class() result (But see the warning section above) or "vector" or "ggplot2" (i.e., objects of class c("gg", "ggplot")) or NULL
-    # typeof: character string. Either one of the typeof() result or NULL
-    # mode: character string. Either one of the mode() result (for non-vector object) or NULL
-    # length: numeric value indicating the length of the object. Not considered if NULL
-    # prop: logical. Are the numeric values between 0 and 1 (proportion)? If TRUE, can be used alone, without considering class, etc.
-    # double.as.integer.allowed: logical. If TRUE, no error is reported in the cheking message if argument is set to typeof == "integer" or class == "integer", while the reality is typeof == "double" or class == "numeric" but the numbers strictly have zero as modulo (remainder of a division). This means that i <- 1, which is typeof(i) -> "double" is considered as integer with double.as.integer.allowed = TRUE. WARNING: data%%1 == 0L but not isTRUE(all.equal(data%%1, 0)) is used here because the argument checks for integers stored as double (does not check for decimal numbers that are approximate integers)
-    # options: a vector of character strings or integers indicating all the possible option values for the data argument, or NULL. Numbers of type "double" are accepted if they have a 0 modulo
-    # all.options.in.data: logical. If TRUE, all of the options must be present at least once in the data argument, and nothing else. If FALSE, some or all of the options must be present in the data argument, and nothing else. Ignored if options is NULL
-    # na.contain: logical. Can the data argument contain NA?
-    # neg.values: logical. Are negative numeric values authorized? Warning: the default setting is TRUE, meaning that, in that case, no check is performed for the presence of negative values. The neg.values argument is activated only when set to FALSE. In addition, (1) neg.values = FALSE can only be used when class, typeof or mode arguments are not NULL, otherwise return an error message, (2) the presence of negative values is not checked with neg.values = FALSE if the tested object is a factor and the following checking message is returned "OBJECT MUST BE MADE OF NON NEGATIVE VALUES BUT IS A FACTOR"
-    # print: logical. Print the message if $problem is TRUE? Warning: set by default to FALSE, which facilitates the control of the checking message output when using fun_check() inside functions. See the example section
-    # data.name: character string indicating the name of the object to test. If NULL, use what is assigned to the data argument for the returned message
-    # fun.name: character string indicating the name of the function checked (i.e., when fun_check() is used to check the arguments of this function). If non-null, the value of fun.name will be added into the message returned by fun_check()
-    # RETURN
-    # A list containing:
-    # $problem: logical. Is there any problem detected?
-    # $text: message indicating the details of the problem, or the absence of problem
-    # $object.name: value of the data.name argument (i.e., name of the checked object if provided, NULL otherwise)
-    # REQUIRED PACKAGES
-    # None
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # None
-    # EXAMPLE
-    # test <- matrix(1:3) ; fun_check(data = test, print = TRUE, class = "vector", mode = "numeric")
-    # see http
-    # DEBUGGING
-    # data = mean ; class = NULL ; typeof = NULL ; mode = NULL ; length = NULL ; prop = FALSE ; double.as.integer.allowed = FALSE ; options = "a" ; all.options.in.data = FALSE ; na.contain = FALSE ; neg.values = TRUE ; print = TRUE ; data.name = NULL ; fun.name = NULL
-    # function name
-    # no used in this function for the error message, to avoid env colliding
-    # end function name
-    # required function checking
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # fun.name checked first because required next
-    if( ! is.null(fun.name)){ # I have to use this way to deal with every kind of class for fun.name
-        if(all(base::class(fun.name) == "character")){ # all() without na.rm -> ok because class(NA) is "logical"
-            if(base::length(fun.name) != 1){
-                tempo.cat <- paste0("ERROR IN fun_check(): THE fun.name ARGUMENT MUST BE A CHARACTER VECTOR OF LENGTH 1: ", paste(fun.name, collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else if(any(is.na(fun.name))){ # normally no NA with is.na()
-                tempo.cat <- paste0("ERROR IN fun_check(): NO ARGUMENT EXCEPT data AND options CAN HAVE NA VALUES\nPROBLEMATIC ARGUMENT IS fun.name")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }else{
-            tempo.cat <- paste0("ERROR IN fun_check(): THE fun.name ARGUMENT MUST BE A CHARACTER VECTOR OF LENGTH 1") # paste(fun.name, collapse = " ") removed here because does not work with objects like function
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end fun.name checked first because required next
-    # arg with no default values
-    mandat.args <- c(
-        "data"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of special classes
-    basic.class <- c(
-        "NULL", # because class(NULL) is "NULL". The NULL aspect will be dealt later
-        "logical", 
-        "integer", 
-        "numeric", 
-        # "complex", 
-        "character"
-        # "matrix", 
-        # "array", 
-        # "data.frame", 
-        # "list", 
-        # "factor", 
-        # "table", 
-        # "expression", 
-        # "name", 
-        # "symbol", 
-        # "function", 
-        # "uneval", 
-        # "environment", 
-        # "ggplot2", 
-        # "ggplot_built", 
-        # "call"
-    )
-    tempo.arg.base <-c( # no names(formals(fun = sys.function(sys.parent(n = 2)))) used with fun_check() to be sure to deal with the correct environment
-        "class", 
-        "typeof", 
-        "mode", 
-        "length", 
-        "prop", 
-        "double.as.integer.allowed", 
-        "options", 
-        "all.options.in.data", 
-        "na.contain", 
-        "neg.values", 
-        "print", 
-        "data.name", 
-        "fun.name"
-    )
-    tempo.class <-list( # no get() used to be sure to deal with the correct environment
-        base::class(class), 
-        base::class(typeof), 
-        base::class(mode), 
-        base::class(length), 
-        base::class(prop), 
-        base::class(double.as.integer.allowed), 
-        base::class(options), 
-        base::class(all.options.in.data), 
-        base::class(na.contain), 
-        base::class(neg.values), 
-        base::class(print), 
-        base::class(data.name), 
-        base::class(fun.name)
-    )
-    tempo <- ! sapply(lapply(tempo.class, FUN = "%in%", basic.class), FUN = all)
-    if(any(tempo)){
-        tempo.cat1 <- tempo.arg.base[tempo]
-        tempo.cat2 <- sapply(tempo.class[tempo], FUN = paste0, collapse = " ")
-        tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": ANY ARGUMENT EXCEPT data MUST HAVE A BASIC CLASS\nPROBLEMATIC ARGUMENT", ifelse(base::length(tempo.cat1) > 1, "S", ""), " AND ASSOCIATED CLASS", ifelse(base::length(tempo.cat1) > 1, "ES ARE", " IS"), ":\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n")) # normally no NA with is.na()
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of special classes
-    # management of NA arguments
-    if(any(is.na(data.name)) | any(is.na(class)) | any(is.na(typeof)) | any(is.na(mode)) | any(is.na(length)) | any(is.na(prop)) | any(is.na(double.as.integer.allowed)) | any(is.na(all.options.in.data)) | any(is.na(na.contain)) | any(is.na(neg.values)) | any(is.na(print)) | any(is.na(fun.name))){ # normally no NA with is.na()
-        tempo <- c("data.name", "class", "typeof", "mode", "length", "prop", "double.as.integer.allowed", "all.options.in.data", "na.contain", "neg.values", "print", "fun.name")[c(any(is.na(data.name)), any(is.na(class)), any(is.na(typeof)), any(is.na(mode)), any(is.na(length)), any(is.na(prop)), any(is.na(double.as.integer.allowed)), any(is.na(all.options.in.data)), any(is.na(na.contain)), any(is.na(neg.values)), any(is.na(print)), any(is.na(fun.name)))]
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": NO ARGUMENT EXCEPT data AND options CAN HAVE NA VALUES\nPROBLEMATIC ARGUMENT", ifelse(length(tempo) > 1, "S ARE", " IS"), ":\n", paste(tempo, collapse = "\n")) # normally no NA with is.na()
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "prop", 
-        "double.as.integer.allowed", 
-        "all.options.in.data", 
-        "na.contain",
-        "neg.values",
-        "print"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){ # normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN fun.check():\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT BE NULL:\n", paste0(tempo.arg[tempo.log], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # dealing with logical
-    # tested below
-    # end dealing with logical
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    # end warning initiation
-    # other checkings
-    if( ! is.null(data.name)){
-        if( ! (base::length(data.name) == 1L & all(base::class(data.name) == "character"))){ # all() without na.rm -> ok because class(NA) is "logical"
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": data.name ARGUMENT MUST BE A SINGLE CHARACTER ELEMENT AND NOT ", paste(data.name, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(is.null(options) & is.null(class) & is.null(typeof) & is.null(mode) &  prop == FALSE & is.null(length)){
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": AT LEAST ONE OF THE options, class, typeof, mode, prop, OR length ARGUMENT MUST BE SPECIFIED (I.E, TRUE FOR prop)")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(options) & ( ! is.null(class) | ! is.null(typeof) | ! is.null(mode) | prop == TRUE)){
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE class, typeof, mode ARGUMENTS MUST BE NULL, AND prop FALSE, IF THE options ARGUMENT IS SPECIFIED\nTHE options ARGUMENT MUST BE NULL IF THE class AND/OR typeof AND/OR mode AND/OR prop ARGUMENT IS SPECIFIED")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (all(base::class(neg.values) == "logical") & base::length(neg.values) == 1L)){ # all() without na.rm -> ok because class(NA) is "logical" 
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE neg.values ARGUMENT MUST BE TRUE OR FALSE ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(neg.values == FALSE & is.null(class) & is.null(typeof) & is.null(mode)){
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE neg.values ARGUMENT CANNOT BE SWITCHED TO FALSE IF class, typeof AND mode ARGUMENTS ARE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(class)){ # may add "formula" and "Date" as in https://renenyffenegger.ch/notes/development/languages/R/functions/class
-        if( ! all(class %in% c("vector", "logical", "integer", "numeric", "complex", "character", "matrix", "array", "data.frame", "list", "factor", "table", "expression", "name", "symbol", "function", "uneval", "environment", "ggplot2", "ggplot_built", "call") & base::length(class) == 1L)){ # length == 1L here because of class(matrix()) since R4.0.0  # all() without na.rm -> ok because class cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT MUST BE ONE OF THESE VALUE:\n\"vector\", \"logical\", \"integer\", \"numeric\", \"complex\", \"character\", \"matrix\", \"array\", \"data.frame\", \"list\", \"factor\", \"table\", \"expression\", \"name\", \"symbol\", \"function\", \"environment\", \"ggplot2\", \"ggplot_built\", \"call\"")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(neg.values == FALSE & ! any(class %in% c("vector", "numeric", "integer", "matrix", "array", "data.frame", "table"))){ # no need of na.rm = TRUE for any() because %in% does not output NA
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT CANNOT BE OTHER THAN \"vector\", \"numeric\", \"integer\", \"matrix\", \"array\", \"data.frame\", \"table\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! is.null(typeof)){ # all the types are here: https://renenyffenegger.ch/notes/development/languages/R/functions/typeof
-        if( ! (all(typeof %in% c("logical", "integer", "double", "complex", "character", "list", "expression", "symbol", "closure", "special", "builtin", "environment", "S4", "language")) & base::length(typeof) == 1L)){ # "language" is the type of object of class "call" # all() without na.rm -> ok because typeof cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT MUST BE ONE OF THESE VALUE:\n\"logical\", \"integer\", \"double\", \"complex\", \"character\", \"list\", \"expression\", \"name\", \"symbol\", \"closure\", \"special\", \"builtin\", \"environment\", \"S4\", \"language\"")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(neg.values == FALSE & ! typeof %in% c("double", "integer")){
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT CANNOT BE OTHER THAN \"double\" OR \"integer\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! is.null(mode)){ # all the types are here: https://renenyffenegger.ch/notes/development/languages/R/functions/typeof
-        if( ! (all(mode %in% c("logical", "numeric", "complex", "character", "list", "expression", "name", "symbol", "function", "environment", "S4", "call")) & base::length(mode) == 1L)){ # all() without na.rm -> ok because mode cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT MUST BE ONE OF THESE VALUE:\n\"logical\", \"numeric\", \"complex\", \"character\", \"list\", \"expression\", \"name\", \"symbol\", \"function\", \"environment\", \"S4\", \"call\"")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(neg.values == FALSE & mode != "numeric"){
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT CANNOT BE OTHER THAN \"numeric\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! is.null(length)){
-        if( ! (is.numeric(length) & base::length(length) == 1L & all( ! grepl(length, pattern = "\\.")))){
-            tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": length ARGUMENT MUST BE A SINGLE INTEGER VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! (is.logical(prop) & base::length(prop) == 1L)){ # is.na() already checked for prop
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": prop ARGUMENT MUST BE TRUE OR FALSE ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if(prop == TRUE){
-        if( ! is.null(class)){
-            if( ! any(class %in% c("vector", "numeric", "matrix", "array", "data.frame", "table"))){ # no need of na.rm = TRUE for any() because %in% does not output NA
-                tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT CANNOT BE OTHER THAN NULL, \"vector\", \"numeric\", \"matrix\", \"array\", \"data.frame\", \"table\" IF prop ARGUMENT IS TRUE") # not integer because prop
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        if( ! is.null(mode)){
-            if(mode != "numeric"){
-                tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT CANNOT BE OTHER THAN NULL OR \"numeric\" IF prop ARGUMENT IS TRUE")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        if( ! is.null(typeof)){
-            if(typeof != "double"){
-                tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT CANNOT BE OTHER THAN NULL OR \"double\" IF prop ARGUMENT IS TRUE")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-    }
-    if( ! (all(base::class(double.as.integer.allowed) == "logical") & base::length(double.as.integer.allowed) == 1L)){ # all() without na.rm -> ok because class() never returns NA
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE double.as.integer.allowed ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(double.as.integer.allowed, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (is.logical(all.options.in.data) & base::length(all.options.in.data) == 1L)){
-        tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": all.options.in.data ARGUMENT MUST BE A SINGLE LOGICAL VALUE (TRUE OR FALSE ONLY): ", paste(all.options.in.data, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (all(base::class(na.contain) == "logical") & base::length(na.contain) == 1L)){ # all() without na.rm -> ok because class() never returns NA
-        tempo.cat <- paste0("ERROR IN fun_check(): THE na.contain ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(na.contain, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (all(base::class(print) == "logical") & base::length(print) == 1L)){ # all() without na.rm -> ok because class() never returns NA
-        tempo.cat <- paste0("ERROR IN fun_check(): THE print ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(print, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # data.name and fun.name tested at the beginning
-    # end other checkings
-    # end second round of checking and data preparation
-    # package checking
-    # end package checking
-    # main code
-    if(is.null(data.name)){
-        data.name <- deparse(substitute(data))
-    }
-    problem <- FALSE
-    text <- paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT")
-    if(( ! is.null(options)) & (all(base::typeof(data) == "character") | all(base::typeof(data) == "integer") | all(base::typeof(data) == "double"))){ # all() without na.rm -> ok because typeof() never returns NA
-        if(all(base::typeof(data) == "double")){
-            if( ! all(data %% 1 == 0L, na.rm = TRUE)){
-                problem <- TRUE
-                text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nBUT IS NOT EVEN TYPE CHARACTER OR INTEGER")
-            }
-        }else{
-            text <- ""
-            if( ! all(data %in% options)){ # no need of na.rm = TRUE for all() because %in% does not output NA
-                problem <- TRUE
-                text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nTHE PROBLEMATIC ELEMENTS OF ", data.name, " ARE: ", paste(unique(data[ ! (data %in% options)]), collapse = " "))
-            }
-            if(all.options.in.data == TRUE){
-                if( ! all(options %in% data)){ # no need of na.rm = TRUE for all() because %in% does not output NA
-                    problem <- TRUE
-                    text <- paste0(ifelse(text == "", "", paste0(text, "\n")), ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE MADE OF ALL THESE OPTIONS: ", paste(options, collapse = " "), "\nTHE MISSING ELEMENTS OF THE options ARGUMENT ARE: ",  paste(unique(options[ ! (options %in% data)]), collapse = " "))
-                }
-            }
-            if( ! is.null(length)){
-                if(base::length(data) != length){
-                    problem <- TRUE
-                    text <- paste0(ifelse(text == "", "", paste0(text, "\n")), ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE LENGTH OF ", data.name, " MUST BE ", length, " AND NOT ", base::length(data))
-                }
-            }
-            if(text == ""){
-                text <- paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT")
-            }
-        }
-    }else if( ! is.null(options)){
-        problem <- TRUE
-        text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nBUT IS NOT EVEN TYPE CHARACTER OR INTEGER")
-    }
-    arg.names <- c("class", "typeof", "mode", "length")
-    if( ! is.null(class)){
-        if(class == "matrix"){ # because of class(matric()) since R4.0.0
-            class <- c("matrix", "array")
-        }else if(class == "factor" & all(base::class(data) %in% c("factor", "ordered"))){ # to deal with ordered factors # all() without na.rm -> ok because class(NA) is "logical"
-            class <- c("factor", "ordered")
-        }
-    }
-    if(is.null(options)){
-        for(i2 in 1:base::length(arg.names)){
-            if( ! is.null(get(arg.names[i2], env = sys.nframe(), inherit = FALSE))){
-                # script to execute
-                tempo.script <- '
+# AIM
+# Check the class, type, mode and length of the data argument
+# Mainly used to check the arguments of other functions
+# Check also other kind of data parameters, is it a proportion? Is it type double but numbers without decimal part?
+# If options == NULL, then at least class or type or mode or length argument must be non-null
+# If options is non-null, then class, type and mode must be NULL, and length can be NULL or specified
+# WARNINGS
+# The function tests what is written in its arguments, even if what is written is incoherent. For instance, fun_check(data = factor(1), class = "factor", mode = "character") will return a problem, whatever the object tested in the data argument, because no object can be class "factor" and mode "character" (factors are class "factor" and mode "numeric"). Of note, length of object of class "environment" is always 0
+# If the tested object is NULL, then the function will always return a checking problem
+# Since R >= 4.0.0, class(matrix()) returns "matrix" "array", and not "matrix" alone as before. However, use argument class = "matrix" to check for matrix object (of class "matrix" "array" in R >= 4.0.0) and use argument class = "array" to check for array object (of class "array" in R >= 4.0.0)
+# ARGUMENTS
+# data: object to test
+# class: character string. Either one of the class() result (But see the warning section above) or "vector" or "ggplot2" (i.e., objects of class c("gg", "ggplot")) or NULL
+# typeof: character string. Either one of the typeof() result or NULL
+# mode: character string. Either one of the mode() result (for non-vector object) or NULL
+# length: numeric value indicating the length of the object. Not considered if NULL
+# prop: logical. Are the numeric values between 0 and 1 (proportion)? If TRUE, can be used alone, without considering class, etc.
+# double.as.integer.allowed: logical. If TRUE, no error is reported in the cheking message if argument is set to typeof == "integer" or class == "integer", while the reality is typeof == "double" or class == "numeric" but the numbers strictly have zero as modulo (remainder of a division). This means that i <- 1, which is typeof(i) -> "double" is considered as integer with double.as.integer.allowed = TRUE. WARNING: data%%1 == 0L but not isTRUE(all.equal(data%%1, 0)) is used here because the argument checks for integers stored as double (does not check for decimal numbers that are approximate integers)
+# options: a vector of character strings or integers indicating all the possible option values for the data argument, or NULL. Numbers of type "double" are accepted if they have a 0 modulo
+# all.options.in.data: logical. If TRUE, all of the options must be present at least once in the data argument, and nothing else. If FALSE, some or all of the options must be present in the data argument, and nothing else. Ignored if options is NULL
+# na.contain: logical. Can the data argument contain NA?
+# neg.values: logical. Are negative numeric values authorized? Warning: the default setting is TRUE, meaning that, in that case, no check is performed for the presence of negative values. The neg.values argument is activated only when set to FALSE. In addition, (1) neg.values = FALSE can only be used when class, typeof or mode arguments are not NULL, otherwise return an error message, (2) the presence of negative values is not checked with neg.values = FALSE if the tested object is a factor and the following checking message is returned "OBJECT MUST BE MADE OF NON NEGATIVE VALUES BUT IS A FACTOR"
+# print: logical. Print the message if $problem is TRUE? Warning: set by default to FALSE, which facilitates the control of the checking message output when using fun_check() inside functions. See the example section
+# data.name: character string indicating the name of the object to test. If NULL, use what is assigned to the data argument for the returned message
+# fun.name: character string indicating the name of the function checked (i.e., when fun_check() is used to check the arguments of this function). If non-null, the value of fun.name will be added into the message returned by fun_check()
+# RETURN
+# A list containing:
+# $problem: logical. Is there any problem detected?
+# $text: message indicating the details of the problem, or the absence of problem
+# $object.name: value of the data.name argument (i.e., name of the checked object if provided, NULL otherwise)
+# REQUIRED PACKAGES
+# None
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# None
+# EXAMPLE
+# test <- matrix(1:3) ; fun_check(data = test, print = TRUE, class = "vector", mode = "numeric")
+# see http
+# DEBUGGING
+# data = mean ; class = NULL ; typeof = NULL ; mode = NULL ; length = NULL ; prop = FALSE ; double.as.integer.allowed = FALSE ; options = "a" ; all.options.in.data = FALSE ; na.contain = FALSE ; neg.values = TRUE ; print = TRUE ; data.name = NULL ; fun.name = NULL
+# function name
+# no used in this function for the error message, to avoid env colliding
+# end function name
+# required function checking
+# end required function checking
+# reserved words
+# end reserved words
+# fun.name checked first because required next
+if( ! is.null(fun.name)){ # I have to use this way to deal with every kind of class for fun.name
+if(all(base::class(fun.name) == "character")){ # all() without na.rm -> ok because class(NA) is "logical"
+if(base::length(fun.name) != 1){
+tempo.cat <- paste0("ERROR IN fun_check(): THE fun.name ARGUMENT MUST BE A CHARACTER VECTOR OF LENGTH 1: ", paste(fun.name, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(any(is.na(fun.name))){ # normally no NA with is.na()
+tempo.cat <- paste0("ERROR IN fun_check(): NO ARGUMENT EXCEPT data AND options CAN HAVE NA VALUES\nPROBLEMATIC ARGUMENT IS fun.name")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+tempo.cat <- paste0("ERROR IN fun_check(): THE fun.name ARGUMENT MUST BE A CHARACTER VECTOR OF LENGTH 1") # paste(fun.name, collapse = " ") removed here because does not work with objects like function
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end fun.name checked first because required next
+# arg with no default values
+mandat.args <- c(
+"data"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
+# end argument primary checking
+# second round of checking and data preparation
+# management of special classes
+basic.class <- c(
+"NULL", # because class(NULL) is "NULL". The NULL aspect will be dealt later
+"logical", 
+"integer", 
+"numeric", 
+# "complex", 
+"character"
+# "matrix", 
+# "array", 
+# "data.frame", 
+# "list", 
+# "factor", 
+# "table", 
+# "expression", 
+# "name", 
+# "symbol", 
+# "function", 
+# "uneval", 
+# "environment", 
+# "ggplot2", 
+# "ggplot_built", 
+# "call"
+)
+tempo.arg.base <-c( # no names(formals(fun = sys.function(sys.parent(n = 2)))) used with fun_check() to be sure to deal with the correct environment
+"class", 
+"typeof", 
+"mode", 
+"length", 
+"prop", 
+"double.as.integer.allowed", 
+"options", 
+"all.options.in.data", 
+"na.contain", 
+"neg.values", 
+"print", 
+"data.name", 
+"fun.name"
+)
+tempo.class <-list( # no get() used to be sure to deal with the correct environment
+base::class(class), 
+base::class(typeof), 
+base::class(mode), 
+base::class(length), 
+base::class(prop), 
+base::class(double.as.integer.allowed), 
+base::class(options), 
+base::class(all.options.in.data), 
+base::class(na.contain), 
+base::class(neg.values), 
+base::class(print), 
+base::class(data.name), 
+base::class(fun.name)
+)
+tempo <- ! sapply(lapply(tempo.class, FUN = "%in%", basic.class), FUN = all)
+if(any(tempo)){
+tempo.cat1 <- tempo.arg.base[tempo]
+tempo.cat2 <- sapply(tempo.class[tempo], FUN = paste0, collapse = " ")
+tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": ANY ARGUMENT EXCEPT data MUST HAVE A BASIC CLASS\nPROBLEMATIC ARGUMENT", ifelse(base::length(tempo.cat1) > 1, "S", ""), " AND ASSOCIATED CLASS", ifelse(base::length(tempo.cat1) > 1, "ES ARE", " IS"), ":\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n")) # normally no NA with is.na()
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of special classes
+# management of NA arguments
+if(any(is.na(data.name)) | any(is.na(class)) | any(is.na(typeof)) | any(is.na(mode)) | any(is.na(length)) | any(is.na(prop)) | any(is.na(double.as.integer.allowed)) | any(is.na(all.options.in.data)) | any(is.na(na.contain)) | any(is.na(neg.values)) | any(is.na(print)) | any(is.na(fun.name))){ # normally no NA with is.na()
+tempo <- c("data.name", "class", "typeof", "mode", "length", "prop", "double.as.integer.allowed", "all.options.in.data", "na.contain", "neg.values", "print", "fun.name")[c(any(is.na(data.name)), any(is.na(class)), any(is.na(typeof)), any(is.na(mode)), any(is.na(length)), any(is.na(prop)), any(is.na(double.as.integer.allowed)), any(is.na(all.options.in.data)), any(is.na(na.contain)), any(is.na(neg.values)), any(is.na(print)), any(is.na(fun.name)))]
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": NO ARGUMENT EXCEPT data AND options CAN HAVE NA VALUES\nPROBLEMATIC ARGUMENT", ifelse(length(tempo) > 1, "S ARE", " IS"), ":\n", paste(tempo, collapse = "\n")) # normally no NA with is.na()
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"prop", 
+"double.as.integer.allowed", 
+"all.options.in.data", 
+"na.contain",
+"neg.values",
+"print"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){ # normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN fun.check():\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT BE NULL:\n", paste0(tempo.arg[tempo.log], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# dealing with logical
+# tested below
+# end dealing with logical
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+# end warning initiation
+# other checkings
+if( ! is.null(data.name)){
+if( ! (base::length(data.name) == 1L & all(base::class(data.name) == "character"))){ # all() without na.rm -> ok because class(NA) is "logical"
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": data.name ARGUMENT MUST BE A SINGLE CHARACTER ELEMENT AND NOT ", paste(data.name, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(is.null(options) & is.null(class) & is.null(typeof) & is.null(mode) &  prop == FALSE & is.null(length)){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": AT LEAST ONE OF THE options, class, typeof, mode, prop, OR length ARGUMENT MUST BE SPECIFIED (I.E, TRUE FOR prop)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(options) & ( ! is.null(class) | ! is.null(typeof) | ! is.null(mode) | prop == TRUE)){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE class, typeof, mode ARGUMENTS MUST BE NULL, AND prop FALSE, IF THE options ARGUMENT IS SPECIFIED\nTHE options ARGUMENT MUST BE NULL IF THE class AND/OR typeof AND/OR mode AND/OR prop ARGUMENT IS SPECIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (all(base::class(neg.values) == "logical") & base::length(neg.values) == 1L)){ # all() without na.rm -> ok because class(NA) is "logical" 
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE neg.values ARGUMENT MUST BE TRUE OR FALSE ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(neg.values == FALSE & is.null(class) & is.null(typeof) & is.null(mode)){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE neg.values ARGUMENT CANNOT BE SWITCHED TO FALSE IF class, typeof AND mode ARGUMENTS ARE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(class)){ # may add "formula" and "Date" as in https://renenyffenegger.ch/notes/development/languages/R/functions/class
+if( ! all(class %in% c("vector", "logical", "integer", "numeric", "complex", "character", "matrix", "array", "data.frame", "list", "factor", "table", "expression", "name", "symbol", "function", "uneval", "environment", "ggplot2", "ggplot_built", "call") & base::length(class) == 1L)){ # length == 1L here because of class(matrix()) since R4.0.0  # all() without na.rm -> ok because class cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT MUST BE ONE OF THESE VALUE:\n\"vector\", \"logical\", \"integer\", \"numeric\", \"complex\", \"character\", \"matrix\", \"array\", \"data.frame\", \"list\", \"factor\", \"table\", \"expression\", \"name\", \"symbol\", \"function\", \"environment\", \"ggplot2\", \"ggplot_built\", \"call\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(neg.values == FALSE & ! any(class %in% c("vector", "numeric", "integer", "matrix", "array", "data.frame", "table"))){ # no need of na.rm = TRUE for any() because %in% does not output NA
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT CANNOT BE OTHER THAN \"vector\", \"numeric\", \"integer\", \"matrix\", \"array\", \"data.frame\", \"table\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(typeof)){ # all the types are here: https://renenyffenegger.ch/notes/development/languages/R/functions/typeof
+if( ! (all(typeof %in% c("logical", "integer", "double", "complex", "character", "list", "expression", "symbol", "closure", "special", "builtin", "environment", "S4", "language")) & base::length(typeof) == 1L)){ # "language" is the type of object of class "call" # all() without na.rm -> ok because typeof cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT MUST BE ONE OF THESE VALUE:\n\"logical\", \"integer\", \"double\", \"complex\", \"character\", \"list\", \"expression\", \"name\", \"symbol\", \"closure\", \"special\", \"builtin\", \"environment\", \"S4\", \"language\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(neg.values == FALSE & ! typeof %in% c("double", "integer")){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT CANNOT BE OTHER THAN \"double\" OR \"integer\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(mode)){ # all the types are here: https://renenyffenegger.ch/notes/development/languages/R/functions/typeof
+if( ! (all(mode %in% c("logical", "numeric", "complex", "character", "list", "expression", "name", "symbol", "function", "environment", "S4", "call")) & base::length(mode) == 1L)){ # all() without na.rm -> ok because mode cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT MUST BE ONE OF THESE VALUE:\n\"logical\", \"numeric\", \"complex\", \"character\", \"list\", \"expression\", \"name\", \"symbol\", \"function\", \"environment\", \"S4\", \"call\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(neg.values == FALSE & mode != "numeric"){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT CANNOT BE OTHER THAN \"numeric\" IF neg.values ARGUMENT IS SWITCHED TO FALSE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(length)){
+if( ! (is.numeric(length) & base::length(length) == 1L & all( ! grepl(length, pattern = "\\.")))){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": length ARGUMENT MUST BE A SINGLE INTEGER VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! (is.logical(prop) & base::length(prop) == 1L)){ # is.na() already checked for prop
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": prop ARGUMENT MUST BE TRUE OR FALSE ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(prop == TRUE){
+if( ! is.null(class)){
+if( ! any(class %in% c("vector", "numeric", "matrix", "array", "data.frame", "table"))){ # no need of na.rm = TRUE for any() because %in% does not output NA
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": class ARGUMENT CANNOT BE OTHER THAN NULL, \"vector\", \"numeric\", \"matrix\", \"array\", \"data.frame\", \"table\" IF prop ARGUMENT IS TRUE") # not integer because prop
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(mode)){
+if(mode != "numeric"){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": mode ARGUMENT CANNOT BE OTHER THAN NULL OR \"numeric\" IF prop ARGUMENT IS TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(typeof)){
+if(typeof != "double"){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": typeof ARGUMENT CANNOT BE OTHER THAN NULL OR \"double\" IF prop ARGUMENT IS TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}
+if( ! (all(base::class(double.as.integer.allowed) == "logical") & base::length(double.as.integer.allowed) == 1L)){ # all() without na.rm -> ok because class() never returns NA
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": THE double.as.integer.allowed ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(double.as.integer.allowed, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (is.logical(all.options.in.data) & base::length(all.options.in.data) == 1L)){
+tempo.cat <- paste0("ERROR IN fun_check()", ifelse(is.null(fun.name), "", paste0(" INSIDE ", fun.name)), ": all.options.in.data ARGUMENT MUST BE A SINGLE LOGICAL VALUE (TRUE OR FALSE ONLY): ", paste(all.options.in.data, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (all(base::class(na.contain) == "logical") & base::length(na.contain) == 1L)){ # all() without na.rm -> ok because class() never returns NA
+tempo.cat <- paste0("ERROR IN fun_check(): THE na.contain ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(na.contain, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (all(base::class(print) == "logical") & base::length(print) == 1L)){ # all() without na.rm -> ok because class() never returns NA
+tempo.cat <- paste0("ERROR IN fun_check(): THE print ARGUMENT MUST BE TRUE OR FALSE ONLY: ", paste(print, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# data.name and fun.name tested at the beginning
+# end other checkings
+# end second round of checking and data preparation
+# package checking
+# end package checking
+# main code
+if(is.null(data.name)){
+data.name <- deparse(substitute(data))
+}
+problem <- FALSE
+text <- paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT")
+if(( ! is.null(options)) & (all(base::typeof(data) == "character") | all(base::typeof(data) == "integer") | all(base::typeof(data) == "double"))){ # all() without na.rm -> ok because typeof() never returns NA
+if(all(base::typeof(data) == "double")){
+if( ! all(data %% 1 == 0L, na.rm = TRUE)){
+problem <- TRUE
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nBUT IS NOT EVEN TYPE CHARACTER OR INTEGER")
+}
+}else{
+text <- ""
+if( ! all(data %in% options)){ # no need of na.rm = TRUE for all() because %in% does not output NA
+problem <- TRUE
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nTHE PROBLEMATIC ELEMENTS OF ", data.name, " ARE: ", paste(unique(data[ ! (data %in% options)]), collapse = " "))
+}
+if(all.options.in.data == TRUE){
+if( ! all(options %in% data)){ # no need of na.rm = TRUE for all() because %in% does not output NA
+problem <- TRUE
+text <- paste0(ifelse(text == "", "", paste0(text, "\n")), ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE MADE OF ALL THESE OPTIONS: ", paste(options, collapse = " "), "\nTHE MISSING ELEMENTS OF THE options ARGUMENT ARE: ",  paste(unique(options[ ! (options %in% data)]), collapse = " "))
+}
+}
+if( ! is.null(length)){
+if(base::length(data) != length){
+problem <- TRUE
+text <- paste0(ifelse(text == "", "", paste0(text, "\n")), ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE LENGTH OF ", data.name, " MUST BE ", length, " AND NOT ", base::length(data))
+}
+}
+if(text == ""){
+text <- paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT")
+}
+}
+}else if( ! is.null(options)){
+problem <- TRUE
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE SOME OF THESE OPTIONS: ", paste(options, collapse = " "), "\nBUT IS NOT EVEN TYPE CHARACTER OR INTEGER")
+}
+arg.names <- c("class", "typeof", "mode", "length")
+if( ! is.null(class)){
+if(class == "matrix"){ # because of class(matric()) since R4.0.0
+class <- c("matrix", "array")
+}else if(class == "factor" & all(base::class(data) %in% c("factor", "ordered"))){ # to deal with ordered factors # all() without na.rm -> ok because class(NA) is "logical"
+class <- c("factor", "ordered")
+}
+}
+if(is.null(options)){
+for(i2 in 1:base::length(arg.names)){
+if( ! is.null(get(arg.names[i2], env = sys.nframe(), inherit = FALSE))){
+# script to execute
+tempo.script <- '
 problem <- TRUE ;
 if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
 text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": THE ", data.name, " OBJECT MUST BE ") ;
@@ -443,75 +443,75 @@ text <- paste0(text, " AND ") ;
 }
 text <- paste0(text, toupper(arg.names[i2]), " ", if(all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) %in% c("matrix", "array"))){"matrix"}else if(all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) %in% c("factor", "ordered"))){"factor"}else{get(arg.names[i2], env = sys.nframe(), inherit = FALSE)})
 ' # no need of na.rm = TRUE for all() because %in% does not output NA
-            # end script to execute
-            if(base::typeof(data) == "double" & double.as.integer.allowed == TRUE & ((arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "integer")) | (arg.names[i2] == "typeof" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "integer")))){ # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names # typeof(data) == "double" means no factor allowed
-                if( ! all(data %% 1 == 0L, na.rm = TRUE)){ # to check integers (use %%, meaning the remaining of a division): see the precedent line. isTRUE(all.equal(data%%1, rep(0, length(data)))) not used because we strictly need zero as a result. Warning: na.rm = TRUE required here for all()
-                    eval(parse(text = tempo.script)) # execute tempo.script
-                }
-            }else if( ! any(all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) %in% c("vector", "ggplot2"))) & ! all(eval(parse(text = paste0(arg.names[i2], "(data)"))) %in% get(arg.names[i2], env = sys.nframe(), inherit = FALSE))){ # test the four c("class", "typeof", "mode", "length") arguments with their corresponding function. No need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for any() because get get(arg.names) does not contain NA
-                eval(parse(text = tempo.script)) # execute tempo.script
-            }else if(arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "vector") & ! (all(base::class(data) %in% "numeric") | all(base::class(data) %in% "integer") | all(base::class(data) %in% "character") | all(base::class(data) %in% "logical"))){ # test class == "vector". No need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names
-                eval(parse(text = tempo.script)) # execute tempo.script
-            }else if(arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "ggplot2") & ! all(base::class(data) %in% c("gg", "ggplot"))){ # test ggplot object # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names # no need of na.rm = TRUE for all() because %in% does not output NA
-                eval(parse(text = tempo.script)) # execute tempo.script
-            }
-            }
-        }
-    }
+# end script to execute
+if(base::typeof(data) == "double" & double.as.integer.allowed == TRUE & ((arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "integer")) | (arg.names[i2] == "typeof" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "integer")))){ # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names # typeof(data) == "double" means no factor allowed
+if( ! all(data %% 1 == 0L, na.rm = TRUE)){ # to check integers (use %%, meaning the remaining of a division): see the precedent line. isTRUE(all.equal(data%%1, rep(0, length(data)))) not used because we strictly need zero as a result. Warning: na.rm = TRUE required here for all()
+eval(parse(text = tempo.script)) # execute tempo.script
+}
+}else if( ! any(all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) %in% c("vector", "ggplot2"))) & ! all(eval(parse(text = paste0(arg.names[i2], "(data)"))) %in% get(arg.names[i2], env = sys.nframe(), inherit = FALSE))){ # test the four c("class", "typeof", "mode", "length") arguments with their corresponding function. No need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for any() because get get(arg.names) does not contain NA
+eval(parse(text = tempo.script)) # execute tempo.script
+}else if(arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "vector") & ! (all(base::class(data) %in% "numeric") | all(base::class(data) %in% "integer") | all(base::class(data) %in% "character") | all(base::class(data) %in% "logical"))){ # test class == "vector". No need of na.rm = TRUE for all() because %in% does not output NA # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names
+eval(parse(text = tempo.script)) # execute tempo.script
+}else if(arg.names[i2] == "class" & all(get(arg.names[i2], env = sys.nframe(), inherit = FALSE) == "ggplot2") & ! all(base::class(data) %in% c("gg", "ggplot"))){ # test ggplot object # no need of na.rm = TRUE for all() because == does not output NA if no NA in left of ==, which is the case for arg.names # no need of na.rm = TRUE for all() because %in% does not output NA
+eval(parse(text = tempo.script)) # execute tempo.script
+}
+}
+}
+}
 if(prop == TRUE & all(base::typeof(data) == "double")){ # all() without na.rm -> ok because typeof(NA) is "logical"
-    if(is.null(data) | any(data < 0 | data > 1, na.rm = TRUE)){ # works if data is NULL # Warning: na.rm = TRUE required here for any() # typeof(data) == "double" means no factor allowed
-        problem <- TRUE
-        if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
-            text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
-        }else{
-            text <- paste0(text, " AND ")
-        }
-        text <- paste0(text, "THE ", data.name, " OBJECT MUST BE DECIMAL VALUES BETWEEN 0 AND 1")
-    }
+if(is.null(data) | any(data < 0 | data > 1, na.rm = TRUE)){ # works if data is NULL # Warning: na.rm = TRUE required here for any() # typeof(data) == "double" means no factor allowed
+problem <- TRUE
+if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
+}else{
+text <- paste0(text, " AND ")
+}
+text <- paste0(text, "THE ", data.name, " OBJECT MUST BE DECIMAL VALUES BETWEEN 0 AND 1")
+}
 }else if(prop == TRUE){
-    problem <- TRUE
-    if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
-        text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
-    }else{
-        text <- paste0(text, " AND ")
-    }
-    text <- paste0(text, "THE ", data.name, " OBJECT MUST BE DECIMAL VALUES BETWEEN 0 AND 1")
+problem <- TRUE
+if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
+}else{
+text <- paste0(text, " AND ")
+}
+text <- paste0(text, "THE ", data.name, " OBJECT MUST BE DECIMAL VALUES BETWEEN 0 AND 1")
 }
 if(all(base::class(data) %in% "expression")){ # no need of na.rm = TRUE for all() because %in% does not output NA
-    data <- as.character(data) # to evaluate the presence of NA
+data <- as.character(data) # to evaluate the presence of NA
 }
 if(na.contain == FALSE & (base::mode(data) %in% c("logical", "numeric", "complex", "character", "list"))){ # before it was ! (class(data) %in% c("function", "environment"))
-    if(any(is.na(data)) == TRUE){ # not on the same line because when data is class envir or function , do not like that # normally no NA with is.na()
-        problem <- TRUE
-        if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
-            text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
-        }else{
-            text <- paste0(text, " AND ")
-        }
-        text <- paste0(text, "THE ", data.name, " OBJECT CONTAINS NA WHILE NOT AUTHORIZED")
-    }
+if(any(is.na(data)) == TRUE){ # not on the same line because when data is class envir or function , do not like that # normally no NA with is.na()
+problem <- TRUE
+if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
+}else{
+text <- paste0(text, " AND ")
+}
+text <- paste0(text, "THE ", data.name, " OBJECT CONTAINS NA WHILE NOT AUTHORIZED")
+}
 }
 if(neg.values == FALSE & all(base::mode(data) %in% "numeric") & ! any(base::class(data) %in% "factor")){ # no need of na.rm = TRUE for all() because %in% does not output NA
-    if(any(data < 0, na.rm = TRUE)){ # Warning: na.rm = TRUE required here for any()
-        problem <- TRUE
-        if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
-            text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
-        }else{
-            text <- paste0(text, " AND ")
-        }
-        text <- paste0(text, "THE ", data.name, " OBJECT MUST BE MADE OF NON NEGATIVE NUMERIC VALUES")
-    }
+if(any(data < 0, na.rm = TRUE)){ # Warning: na.rm = TRUE required here for any()
+problem <- TRUE
+if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
+}else{
+text <- paste0(text, " AND ")
+}
+text <- paste0(text, "THE ", data.name, " OBJECT MUST BE MADE OF NON NEGATIVE NUMERIC VALUES")
+}
 }else if(neg.values == FALSE){
-    problem <- TRUE
-    if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
-        text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
-    }else{
-        text <- paste0(text, " AND ")
-    }
-    text <- paste0(text, "THE ", data.name, " OBJECT MUST BE MADE OF NON NEGATIVE VALUES BUT IS ", ifelse(any(base::class(data) %in% "factor"), "A FACTOR", "NOT EVEN MODE NUMERIC"))
+problem <- TRUE
+if(identical(text, paste0(ifelse(is.null(fun.name), "", paste0("IN ", fun.name, ": ")), "NO PROBLEM DETECTED FOR THE ", data.name, " OBJECT"))){
+text <- paste0(ifelse(is.null(fun.name), "ERROR", paste0("ERROR IN ", fun.name)), ": ")
+}else{
+text <- paste0(text, " AND ")
+}
+text <- paste0(text, "THE ", data.name, " OBJECT MUST BE MADE OF NON NEGATIVE VALUES BUT IS ", ifelse(any(base::class(data) %in% "factor"), "A FACTOR", "NOT EVEN MODE NUMERIC"))
 }
 if(print == TRUE & problem == TRUE){
-    cat(paste0("\n\n================\n\n", text, "\n\n================\n\n"))
+cat(paste0("\n\n================\n\n", text, "\n\n================\n\n"))
 }
 # output
 output <- list(problem = problem, text = text, object.name = data.name)
@@ -525,104 +525,104 @@ return(output)
 
 
 fun_secu <- function(pos = 1, name = NULL){
-    # AIM
-    # Verify that variables in the environment defined by the pos parameter are not present in the above environment (following R Scope). This can be used to avoid R scope preference of functions like get()
-    # ARGUMENTS
-    # pos: single integer indicating the position of the environment checked (argument n of parent.frame()). Value 1 means one step above the fun_secu() local environment (by default). This means that when fun_secu(pos = 1) is used inside a function A, it checks if variables in the local environment of this function A are also present in above environments (following R Scope). When fun_secu(pos = 1) is used in the Global environment, it checks the objects of this environment
-    # name: single character string indicating the name of the function checked. If NULL, fun_secu() checks all the variables of the environment indicated by pos, as explained in the pos argument description. If non-null, fun_secu() checks all the variables presents in the local env of the function will be checked in the above envs (which includes the working environment (Global env)
-    # RETURN
-    # A character string of the local variables that match variables in the different environments of the R scope, or NULL if no match
-    # REQUIRED PACKAGES
-    # None
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_secu()
-    # fun_secu(pos = 2)
-    # mean <- 0 ; fun1 <- function(){sd <- 1 ; fun_secu(name = as.character(sys.calls()[[length(sys.calls())]]))} ; fun2 <- function(){cor <- 2 ; fun1()} ; fun1() ; fun2() ; rm(mean) # sys.calls() gives the function name at top stack of the imbricated functions, sys.calls()[[length(sys.calls())]] the name of the just above function. This can also been used for the above function: as.character(sys.call(1))
-    # test.pos <- 2 ; mean <- 0 ; fun1 <- function(){sd <- 1 ; fun_secu(pos = test.pos, name = if(length(sys.calls()) >= test.pos){as.character(sys.calls()[[length(sys.calls()) + 1 - test.pos]])}else{search()[ (1:length(search()))[test.pos - length(sys.calls())]]})} ; fun2 <- function(){cor <- 2 ; fun1()} ; fun1() ; fun2() ; rm(mean) # for argument name, here is a way to have the name of the tested environment according to test.pos value
-    # DEBUGGING
-    # pos = 1 ; name = NULL # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument primary checking
-    # arg with no default values
-    # end arg with no default values
-    # using fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = pos, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(name)){
-        tempo <- fun_check(data = name, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <- c(
-        "pos"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT BE NULL:", paste0(tempo.arg[tempo.log], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # end second round of checking and data preparation
-    # main code
-    # match.list <- vector("list", length = (length(sys.calls()) - 1 + length(search()) + ifelse(length(sys.calls()) == 1L, -1, 0))) # match.list is a list of all the environment tested (local of functions and R envs), length(sys.calls()) - 1 to remove the level of the fun_secu() function, sys.calls() giving all the names of the imbricated functions, including fun_secu, ifelse(length(sys.calls()) == 1L, -1, 0) to remove Global env if this one is tested
-    tempo.name <- rev(as.character(unlist(sys.calls()))) # get names of frames (i.e., enclosed env)
-    tempo.frame <- rev(sys.frames())  # get frames (i.e., enclosed env)
-    # dealing with source()
-    # source() used in the Global env creates three frames above the Global env, which should be removed because not very interesting for variable duplications. Add a <<-(sys.frames()) in this code and source anova_contrasts code to see this. With ls(a[[4]]), we can see the content of each env, which are probably elements of source()
-    if(any(sapply(tempo.frame, FUN = environmentName) %in% "R_GlobalEnv")){
-        global.pos <- which(sapply(tempo.frame, FUN = environmentName) %in% "R_GlobalEnv")
-        # remove the global env (because already in search(), and all the oabove env
-        tempo.name <- tempo.name[-c(global.pos:length(tempo.frame))]
-        tempo.frame <- tempo.frame[-c(global.pos:length(tempo.frame))]
-    }
-    # end dealing with source()
-    # might have a problem if(length(tempo.name) == 0L){
-    match.list <- vector("list", length = length(tempo.name) + length(search())) # match.list is a list of all the environment tested (local of functions and R envs), length(sys.calls()) - 1 to remove the level of the fun_secu() function, sys.calls() giving all the names of the imbricated functions, including fun_secu, ifelse(length(sys.calls()) == 1L, -1, 0) to remove Global env if this one is tested
-    ls.names <- c(tempo.name, search()) # names of the functions + names of the search() environments
-    ls.input <- c(tempo.frame, as.list(search())) # environements of the functions + names of the search() environments
-    names(match.list) <- ls.names # 
-    match.list <- match.list[-c(1:(pos + 1))] # because we check only above pos
-    ls.tested <- ls.input[[pos + 1]]
-    ls.input <- ls.input[-c(1:(pos + 1))]
-    for(i1 in 1:length(match.list)){
-        if(any(ls(name = ls.input[[i1]], all.names = TRUE) %in% ls(name = ls.tested, all.names = TRUE))){
-            match.list[i1] <- list(ls(name = ls.input[[i1]], all.names = TRUE)[ls(name = ls.input[[i1]], all.names = TRUE) %in% ls(name = ls.tested, all.names = TRUE)])
-        }
-    }
-    if( ! all(sapply(match.list, FUN = is.null))){
-        output <- paste0("SOME VARIABLES ", ifelse(is.null(name), "OF THE CHECKED ENVIRONMENT", paste0("OF ", name)), " ARE ALSO PRESENT IN :\n", paste0(names(match.list[ ! sapply(match.list, FUN = is.null)]), ": ", sapply(match.list[ ! sapply(match.list, FUN = is.null)], FUN = paste0, collapse = " "), collapse = "\n"))
-    }else{
-        output <- NULL
-    }
-    return(output)
+# AIM
+# Verify that variables in the environment defined by the pos parameter are not present in the above environment (following R Scope). This can be used to avoid R scope preference of functions like get()
+# ARGUMENTS
+# pos: single integer indicating the position of the environment checked (argument n of parent.frame()). Value 1 means one step above the fun_secu() local environment (by default). This means that when fun_secu(pos = 1) is used inside a function A, it checks if variables in the local environment of this function A are also present in above environments (following R Scope). When fun_secu(pos = 1) is used in the Global environment, it checks the objects of this environment
+# name: single character string indicating the name of the function checked. If NULL, fun_secu() checks all the variables of the environment indicated by pos, as explained in the pos argument description. If non-null, fun_secu() checks all the variables presents in the local env of the function will be checked in the above envs (which includes the working environment (Global env)
+# RETURN
+# A character string of the local variables that match variables in the different environments of the R scope, or NULL if no match
+# REQUIRED PACKAGES
+# None
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_secu()
+# fun_secu(pos = 2)
+# mean <- 0 ; fun1 <- function(){sd <- 1 ; fun_secu(name = as.character(sys.calls()[[length(sys.calls())]]))} ; fun2 <- function(){cor <- 2 ; fun1()} ; fun1() ; fun2() ; rm(mean) # sys.calls() gives the function name at top stack of the imbricated functions, sys.calls()[[length(sys.calls())]] the name of the just above function. This can also been used for the above function: as.character(sys.call(1))
+# test.pos <- 2 ; mean <- 0 ; fun1 <- function(){sd <- 1 ; fun_secu(pos = test.pos, name = if(length(sys.calls()) >= test.pos){as.character(sys.calls()[[length(sys.calls()) + 1 - test.pos]])}else{search()[ (1:length(search()))[test.pos - length(sys.calls())]]})} ; fun2 <- function(){cor <- 2 ; fun1()} ; fun1() ; fun2() ; rm(mean) # for argument name, here is a way to have the name of the tested environment according to test.pos value
+# DEBUGGING
+# pos = 1 ; name = NULL # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument primary checking
+# arg with no default values
+# end arg with no default values
+# using fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = pos, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(name)){
+tempo <- fun_check(data = name, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <- c(
+"pos"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT BE NULL:", paste0(tempo.arg[tempo.log], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# end second round of checking and data preparation
+# main code
+# match.list <- vector("list", length = (length(sys.calls()) - 1 + length(search()) + ifelse(length(sys.calls()) == 1L, -1, 0))) # match.list is a list of all the environment tested (local of functions and R envs), length(sys.calls()) - 1 to remove the level of the fun_secu() function, sys.calls() giving all the names of the imbricated functions, including fun_secu, ifelse(length(sys.calls()) == 1L, -1, 0) to remove Global env if this one is tested
+tempo.name <- rev(as.character(unlist(sys.calls()))) # get names of frames (i.e., enclosed env)
+tempo.frame <- rev(sys.frames())  # get frames (i.e., enclosed env)
+# dealing with source()
+# source() used in the Global env creates three frames above the Global env, which should be removed because not very interesting for variable duplications. Add a <<-(sys.frames()) in this code and source anova_contrasts code to see this. With ls(a[[4]]), we can see the content of each env, which are probably elements of source()
+if(any(sapply(tempo.frame, FUN = environmentName) %in% "R_GlobalEnv")){
+global.pos <- which(sapply(tempo.frame, FUN = environmentName) %in% "R_GlobalEnv")
+# remove the global env (because already in search(), and all the oabove env
+tempo.name <- tempo.name[-c(global.pos:length(tempo.frame))]
+tempo.frame <- tempo.frame[-c(global.pos:length(tempo.frame))]
+}
+# end dealing with source()
+# might have a problem if(length(tempo.name) == 0L){
+match.list <- vector("list", length = length(tempo.name) + length(search())) # match.list is a list of all the environment tested (local of functions and R envs), length(sys.calls()) - 1 to remove the level of the fun_secu() function, sys.calls() giving all the names of the imbricated functions, including fun_secu, ifelse(length(sys.calls()) == 1L, -1, 0) to remove Global env if this one is tested
+ls.names <- c(tempo.name, search()) # names of the functions + names of the search() environments
+ls.input <- c(tempo.frame, as.list(search())) # environements of the functions + names of the search() environments
+names(match.list) <- ls.names # 
+match.list <- match.list[-c(1:(pos + 1))] # because we check only above pos
+ls.tested <- ls.input[[pos + 1]]
+ls.input <- ls.input[-c(1:(pos + 1))]
+for(i1 in 1:length(match.list)){
+if(any(ls(name = ls.input[[i1]], all.names = TRUE) %in% ls(name = ls.tested, all.names = TRUE))){
+match.list[i1] <- list(ls(name = ls.input[[i1]], all.names = TRUE)[ls(name = ls.input[[i1]], all.names = TRUE) %in% ls(name = ls.tested, all.names = TRUE)])
+}
+}
+if( ! all(sapply(match.list, FUN = is.null))){
+output <- paste0("SOME VARIABLES ", ifelse(is.null(name), "OF THE CHECKED ENVIRONMENT", paste0("OF ", name)), " ARE ALSO PRESENT IN :\n", paste0(names(match.list[ ! sapply(match.list, FUN = is.null)]), ": ", sapply(match.list[ ! sapply(match.list, FUN = is.null)], FUN = paste0, collapse = " "), collapse = "\n"))
+}else{
+output <- NULL
+}
+return(output)
 }
 
 
@@ -638,273 +638,273 @@ fun_secu <- function(pos = 1, name = NULL){
 # -> transferred into the cute package
 # Do not modify this function in cute_little_R_function anymore. See the cute repo
 fun_info <- function(
-    data, 
-    n = NULL, 
-    warn.print = TRUE
+data, 
+n = NULL, 
+warn.print = TRUE
 ){
-    # AIM
-    # Provide a broad description of an object
-    # WARNINGS
-    # None
-    # ARGUMENTS
-    # data: object to analyse
-    # n: positive integer value indicating the n first number of elements to display per compartment of the output list (i.e., head(..., n)). Write NULL to return all the elements. Does not apply for the $STRUCTURE compartment output
-    # warn.print: logical. Print potential warnings at the end of the execution? If FALSE the warning messages are added in the output list as an additional compartment (or NULL if no message).
-    # RETURN
-    # A list containing information, depending on the class and type of data. The backbone is generally:
-    # $NAME: name of the object
-    # $CLASS: class of the object (class() value)
-    # $TYPE: type of the object (typeof() value)
-    # $LENGTH: length of the object (length() value)
-    # $NA.NB: number of NA and NaN (only for type "logical", "integer", "double", "complex", "character" or "list")
-    # $HEAD: head of the object (head() value)
-    # $TAIL: tail of the object (tail() value)
-    # $DIMENSION: dimension (only for object with dimensions)
-    # $SUMMARY: object summary (summary() value)
-    # $STRUCTURE: object structure (str() value)
-    # $WARNING: warning messages (only if the warn.print argument is FALSE)
-    # If data is made of numerics, provide also:
-    # $INF.NB: number of Inf and -Inf
-    # $RANGE: range after removing Inf and NA
-    # $SUM: sum after removing Inf and NA
-    # $MEAN: mean after removing Inf and NA
-    # If data is a 2D object, provide also:
-    # $ROW_NAMES: row names
-    # $COL_NAMES: column names
-    # If data is a data frame, provide also:
-    # $COLUMN_TYPE: type of each column (typeof() value)
-    # If data is a list, provide also:
-    # $COMPARTMENT_NAMES: names of the comprtments
-    # $COMPARTMENT_TYPE: type of each compartment (typeof() value)
-    # REQUIRED PACKAGES
-    # None
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # fun_check()
-    # fun_get_message()
-    # EXAMPLE
-    # fun_info(data = 1:3)
-    # see http
-    # DEBUGGING
-    # mat1 <- matrix(1:3) ; data = env1 ; n = NULL ; warn.print = TRUE # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check", 
-        "fun_get_message"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # arg with no default values
-    mandat.args <- c(
-        "data"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if( ! is.null(n)){
-        tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = n, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){ # normally no NA
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "data", 
-        # "n", # because can be NULL
-        "warn.print"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    # warn.count <- 0 # not required
-    # end warning initiation
-    # other checkings
-    if( ! is.null(n)){
-        if(n < 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A POSITIVE AND NON NULL INTEGER")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(is.finite(n)){
-            # warn.count <- warn.count + 1
-            tempo.warn <- paste0("SOME COMPARTMENTS CAN BE TRUNCATED (n ARGUMENT IS ", n, ")")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end other checkings
-    # reserved word checking
-    # end reserved word checking
-    # end second round of checking and data preparation
-    # package checking
-    # end package checking
-    # main code
-    # new environment
-    env.name <- paste0("env", as.numeric(Sys.time()))
-    if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
-        tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        assign(env.name, new.env())
-        assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
-    }
-    # end new environment
-    data.name <- deparse(substitute(data))
-    output <- list("NAME" = data.name)
-    tempo.try.error <- fun_get_message(data = "class(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- list("CLASS" = class(data))
-        output <- c(output, tempo)
-    }
-    tempo.try.error <- fun_get_message(data = "typeof(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- list("TYPE" = typeof(data))
-        output <- c(output, tempo)
-    }
-    tempo.try.error <- fun_get_message(data = "length(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- list("LENGTH" = length(data))
-        output <- c(output, tempo)
-    }
-    if(all(typeof(data) %in% c("integer", "numeric", "double")) & ! any(class(data) %in% "factor")){ # all() without na.rm -> ok because typeof(NA) is "logical" # any() without na.rm -> ok because class(NA) is "logical"
-        tempo <- list("INF.NB" = sum(is.infinite(data)))
-        output <- c(output, tempo)
-        tempo <- list("RANGE" = range(data[ ! is.infinite(data)], na.rm = TRUE))
-        output <- c(output, tempo)
-        tempo <- list("SUM" = sum(data[ ! is.infinite(data)], na.rm = TRUE))
-        output <- c(output, tempo)
-        tempo <- list("MEAN" = mean(data[ ! is.infinite(data)], na.rm = TRUE))
-        output <- c(output, tempo)
-    }
-    if(all(typeof(data) %in% c("logical", "integer", "double", "complex", "character", "list"))){ # all() without na.rm -> ok because typeof(NA) is "logical"
-        tempo.try.error <- fun_get_message(data = "is.na(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-        if(is.null(tempo.try.error)){
-            tempo <- list("NA.NB" = sum(is.na(data)))
-            output <- c(output, tempo)
-        }
-    }
-    tempo.try.error <- fun_get_message(data = "head(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- list("HEAD" = head(data))
-        output <- c(output, tempo)
-        tempo <- list("TAIL" = tail(data)) # no reason that tail() does not work if head() works
-        output <- c(output, tempo)
-    }
-    tempo.try.error <- fun_get_message(data = "dim(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        if(length(dim(data)) > 0){
-            tempo <- list("DIMENSION" = dim(data))
-            if(length(tempo[[1]]) == 2L){
-                names(tempo[[1]]) <- c("NROW", "NCOL")
-            }
-            output <- c(output, tempo)
-        }
-    }
-    if(all(class(data) == "data.frame") | all(class(data) %in% c("matrix", "array")) | all(class(data) == "table")){ # all() without na.rm -> ok because typeof(NA) is "logical"
-        if(length(dim(data)) > 1){ # to avoid 1D table
-            tempo <- list("ROW_NAMES" = dimnames(data)[[1]])
-            output <- c(output, tempo)
-            tempo <- list("COLUM_NAMES" = dimnames(data)[[2]])
-            output <- c(output, tempo)
-        }
-    }
-    tempo.try.error <- fun_get_message(data = "summary(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- list("SUMMARY" = summary(data))
-        output <- c(output, tempo)
-    }
-    tempo.try.error <- fun_get_message(data = "noquote(matrix(capture.output(str(data))))", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
-    if(is.null(tempo.try.error)){
-        tempo <- capture.output(str(data))
-        tempo <- list("STRUCTURE" = noquote(matrix(tempo, dimnames = list(rep("", length(tempo)), "")))) # str() print automatically, ls.str() not but does not give the order of the data.frame
-        output <- c(output, tempo)
-    }
-    if(all(class(data) == "data.frame")){ # all() without na.rm -> ok because class(NA) is "logical"
-        tempo <- list("COLUMN_TYPE" = sapply(data, FUN = "typeof"))
-        if(any(sapply(data, FUN = "class") %in% "factor")){ # if an ordered factor is present, then sapply(data, FUN = "class") return a list but works with any(sapply(data, FUN = "class") %in% "factor") # any() without na.rm -> ok because class(NA) is "logical"
-            tempo.class <- sapply(data, FUN = "class")
-            if(any(unlist(tempo.class) %in% "ordered")){ # any() without na.rm -> ok because class(NA) is "logical"
-                tempo2 <- sapply(tempo.class, paste, collapse = " ") # paste the "ordered" factor" in "ordered factor"
-            }else{
-                tempo2 <- unlist(tempo.class)
-            }
-            tempo[["COLUMN_TYPE"]][grepl(x = tempo2, pattern = "factor")] <- tempo2[grepl(x = tempo2, pattern = "factor")]
-        }
-        output <- c(output, tempo)
-    }
-    if(all(class(data) == "list")){ # all() without na.rm -> ok because class(NA) is "logical"
-        tempo <- list("COMPARTMENT_NAMES" = names(data))
-        output <- c(output, tempo)
-        tempo <- list("COMPARTMENT_TYPE" = sapply(data, FUN = "typeof"))
-        if(any(unlist(sapply(data, FUN = "class")) %in% "factor")){ # if an ordered factor is present, then sapply(data, FUN = "class") return a list but works with any(sapply(data, FUN = "class") %in% "factor")  # any() without na.rm -> ok because class(NA) is "logical"
-            tempo.class <- sapply(data, FUN = "class")
-            if(any(unlist(tempo.class) %in% "ordered")){ # any() without na.rm -> ok because class(NA) is "logical"
-                tempo2 <- sapply(tempo.class, paste, collapse = " ") # paste the "ordered" factor" in "ordered factor"
-            }else{
-                tempo2 <- unlist(tempo.class)
-            }
-            tempo[["COMPARTMENT_TYPE"]][grepl(x = tempo2, pattern = "factor")] <- tempo2[grepl(x = tempo2, pattern = "factor")]
-        }
-        output <- c(output, tempo)
-    }
-    if( ! is.null(n)){
-        output[names(output) != "STRUCTURE"] <- lapply(X = output[names(output) != "STRUCTURE"], FUN = head, n = n, simplify = FALSE)
-    }
-    # output
-    if(warn.print == FALSE){
-        output <- c(output, WARNING = warn)
-    }else if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    return(output)
-    # end output
-    # end main code
+# AIM
+# Provide a broad description of an object
+# WARNINGS
+# None
+# ARGUMENTS
+# data: object to analyse
+# n: positive integer value indicating the n first number of elements to display per compartment of the output list (i.e., head(..., n)). Write NULL to return all the elements. Does not apply for the $STRUCTURE compartment output
+# warn.print: logical. Print potential warnings at the end of the execution? If FALSE the warning messages are added in the output list as an additional compartment (or NULL if no message).
+# RETURN
+# A list containing information, depending on the class and type of data. The backbone is generally:
+# $NAME: name of the object
+# $CLASS: class of the object (class() value)
+# $TYPE: type of the object (typeof() value)
+# $LENGTH: length of the object (length() value)
+# $NA.NB: number of NA and NaN (only for type "logical", "integer", "double", "complex", "character" or "list")
+# $HEAD: head of the object (head() value)
+# $TAIL: tail of the object (tail() value)
+# $DIMENSION: dimension (only for object with dimensions)
+# $SUMMARY: object summary (summary() value)
+# $STRUCTURE: object structure (str() value)
+# $WARNING: warning messages (only if the warn.print argument is FALSE)
+# If data is made of numerics, provide also:
+# $INF.NB: number of Inf and -Inf
+# $RANGE: range after removing Inf and NA
+# $SUM: sum after removing Inf and NA
+# $MEAN: mean after removing Inf and NA
+# If data is a 2D object, provide also:
+# $ROW_NAMES: row names
+# $COL_NAMES: column names
+# If data is a data frame, provide also:
+# $COLUMN_TYPE: type of each column (typeof() value)
+# If data is a list, provide also:
+# $COMPARTMENT_NAMES: names of the comprtments
+# $COMPARTMENT_TYPE: type of each compartment (typeof() value)
+# REQUIRED PACKAGES
+# None
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# fun_check()
+# fun_get_message()
+# EXAMPLE
+# fun_info(data = 1:3)
+# see http
+# DEBUGGING
+# mat1 <- matrix(1:3) ; data = env1 ; n = NULL ; warn.print = TRUE # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check", 
+"fun_get_message"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words
+# end reserved words
+# arg with no default values
+mandat.args <- c(
+"data"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if( ! is.null(n)){
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = n, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){ # normally no NA
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"data", 
+# "n", # because can be NULL
+"warn.print"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+# warn.count <- 0 # not required
+# end warning initiation
+# other checkings
+if( ! is.null(n)){
+if(n < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A POSITIVE AND NON NULL INTEGER")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(is.finite(n)){
+# warn.count <- warn.count + 1
+tempo.warn <- paste0("SOME COMPARTMENTS CAN BE TRUNCATED (n ARGUMENT IS ", n, ")")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end other checkings
+# reserved word checking
+# end reserved word checking
+# end second round of checking and data preparation
+# package checking
+# end package checking
+# main code
+# new environment
+env.name <- paste0("env", as.numeric(Sys.time()))
+if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
+}
+# end new environment
+data.name <- deparse(substitute(data))
+output <- list("NAME" = data.name)
+tempo.try.error <- fun_get_message(data = "class(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("CLASS" = class(data))
+output <- c(output, tempo)
+}
+tempo.try.error <- fun_get_message(data = "typeof(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("TYPE" = typeof(data))
+output <- c(output, tempo)
+}
+tempo.try.error <- fun_get_message(data = "length(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("LENGTH" = length(data))
+output <- c(output, tempo)
+}
+if(all(typeof(data) %in% c("integer", "numeric", "double")) & ! any(class(data) %in% "factor")){ # all() without na.rm -> ok because typeof(NA) is "logical" # any() without na.rm -> ok because class(NA) is "logical"
+tempo <- list("INF.NB" = sum(is.infinite(data)))
+output <- c(output, tempo)
+tempo <- list("RANGE" = range(data[ ! is.infinite(data)], na.rm = TRUE))
+output <- c(output, tempo)
+tempo <- list("SUM" = sum(data[ ! is.infinite(data)], na.rm = TRUE))
+output <- c(output, tempo)
+tempo <- list("MEAN" = mean(data[ ! is.infinite(data)], na.rm = TRUE))
+output <- c(output, tempo)
+}
+if(all(typeof(data) %in% c("logical", "integer", "double", "complex", "character", "list"))){ # all() without na.rm -> ok because typeof(NA) is "logical"
+tempo.try.error <- fun_get_message(data = "is.na(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("NA.NB" = sum(is.na(data)))
+output <- c(output, tempo)
+}
+}
+tempo.try.error <- fun_get_message(data = "head(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("HEAD" = head(data))
+output <- c(output, tempo)
+tempo <- list("TAIL" = tail(data)) # no reason that tail() does not work if head() works
+output <- c(output, tempo)
+}
+tempo.try.error <- fun_get_message(data = "dim(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+if(length(dim(data)) > 0){
+tempo <- list("DIMENSION" = dim(data))
+if(length(tempo[[1]]) == 2L){
+names(tempo[[1]]) <- c("NROW", "NCOL")
+}
+output <- c(output, tempo)
+}
+}
+if(all(class(data) == "data.frame") | all(class(data) %in% c("matrix", "array")) | all(class(data) == "table")){ # all() without na.rm -> ok because typeof(NA) is "logical"
+if(length(dim(data)) > 1){ # to avoid 1D table
+tempo <- list("ROW_NAMES" = dimnames(data)[[1]])
+output <- c(output, tempo)
+tempo <- list("COLUM_NAMES" = dimnames(data)[[2]])
+output <- c(output, tempo)
+}
+}
+tempo.try.error <- fun_get_message(data = "summary(data)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- list("SUMMARY" = summary(data))
+output <- c(output, tempo)
+}
+tempo.try.error <- fun_get_message(data = "noquote(matrix(capture.output(str(data))))", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))
+if(is.null(tempo.try.error)){
+tempo <- capture.output(str(data))
+tempo <- list("STRUCTURE" = noquote(matrix(tempo, dimnames = list(rep("", length(tempo)), "")))) # str() print automatically, ls.str() not but does not give the order of the data.frame
+output <- c(output, tempo)
+}
+if(all(class(data) == "data.frame")){ # all() without na.rm -> ok because class(NA) is "logical"
+tempo <- list("COLUMN_TYPE" = sapply(data, FUN = "typeof"))
+if(any(sapply(data, FUN = "class") %in% "factor")){ # if an ordered factor is present, then sapply(data, FUN = "class") return a list but works with any(sapply(data, FUN = "class") %in% "factor") # any() without na.rm -> ok because class(NA) is "logical"
+tempo.class <- sapply(data, FUN = "class")
+if(any(unlist(tempo.class) %in% "ordered")){ # any() without na.rm -> ok because class(NA) is "logical"
+tempo2 <- sapply(tempo.class, paste, collapse = " ") # paste the "ordered" factor" in "ordered factor"
+}else{
+tempo2 <- unlist(tempo.class)
+}
+tempo[["COLUMN_TYPE"]][grepl(x = tempo2, pattern = "factor")] <- tempo2[grepl(x = tempo2, pattern = "factor")]
+}
+output <- c(output, tempo)
+}
+if(all(class(data) == "list")){ # all() without na.rm -> ok because class(NA) is "logical"
+tempo <- list("COMPARTMENT_NAMES" = names(data))
+output <- c(output, tempo)
+tempo <- list("COMPARTMENT_TYPE" = sapply(data, FUN = "typeof"))
+if(any(unlist(sapply(data, FUN = "class")) %in% "factor")){ # if an ordered factor is present, then sapply(data, FUN = "class") return a list but works with any(sapply(data, FUN = "class") %in% "factor")  # any() without na.rm -> ok because class(NA) is "logical"
+tempo.class <- sapply(data, FUN = "class")
+if(any(unlist(tempo.class) %in% "ordered")){ # any() without na.rm -> ok because class(NA) is "logical"
+tempo2 <- sapply(tempo.class, paste, collapse = " ") # paste the "ordered" factor" in "ordered factor"
+}else{
+tempo2 <- unlist(tempo.class)
+}
+tempo[["COMPARTMENT_TYPE"]][grepl(x = tempo2, pattern = "factor")] <- tempo2[grepl(x = tempo2, pattern = "factor")]
+}
+output <- c(output, tempo)
+}
+if( ! is.null(n)){
+output[names(output) != "STRUCTURE"] <- lapply(X = output[names(output) != "STRUCTURE"], FUN = head, n = n, simplify = FALSE)
+}
+# output
+if(warn.print == FALSE){
+output <- c(output, WARNING = warn)
+}else if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+return(output)
+# end output
+# end main code
 }
 
 
@@ -912,62 +912,62 @@ fun_info <- function(
 
 
 fun_head <- function(
-    data1, 
-    n = 6, 
-    side = "l"
+data1, 
+n = 6, 
+side = "l"
 ){
-    # AIM
-    # as head() but display the left or right head of big 2D objects
-    # ARGUMENTS
-    # data1: any object but more dedicated for matrix, data frame or table
-    # n: as in head() but for for matrix, data frame or table, number of dimension to print (10 means 10 rows and columns)
-    # side: either "l" or "r" for the left or right side of the 2D object (only for matrix, data frame or table)
-    # BEWARE: other arguments of head() not used
-    # RETURN
-    # the head
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # obs1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:6], LETTERS[1:5])) ; obs1 ; fun_head(obs1, 3)
-    # DEBUGGING
-    # data1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = n, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = side, options = c("l", "r"), length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
-        return(head(data1, n))
-    }else{
-        obs.dim <- dim(data1)
-        row <- 1:ifelse(obs.dim[1] < n, obs.dim[1], n)
-        if(side == "l"){
-            col <- 1:ifelse(obs.dim[2] < n, obs.dim[2], n)
-        }
-        if(side == "r"){
-            col <- ifelse(obs.dim[2] < n, 1, obs.dim[2] - n + 1):obs.dim[2]
-        }
-        return(data1[row, col])
-    }
+# AIM
+# as head() but display the left or right head of big 2D objects
+# ARGUMENTS
+# data1: any object but more dedicated for matrix, data frame or table
+# n: as in head() but for for matrix, data frame or table, number of dimension to print (10 means 10 rows and columns)
+# side: either "l" or "r" for the left or right side of the 2D object (only for matrix, data frame or table)
+# BEWARE: other arguments of head() not used
+# RETURN
+# the head
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# obs1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:6], LETTERS[1:5])) ; obs1 ; fun_head(obs1, 3)
+# DEBUGGING
+# data1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = side, options = c("l", "r"), length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
+return(head(data1, n))
+}else{
+obs.dim <- dim(data1)
+row <- 1:ifelse(obs.dim[1] < n, obs.dim[1], n)
+if(side == "l"){
+col <- 1:ifelse(obs.dim[2] < n, obs.dim[2], n)
+}
+if(side == "r"){
+col <- ifelse(obs.dim[2] < n, 1, obs.dim[2] - n + 1):obs.dim[2]
+}
+return(data1[row, col])
+}
 }
 
 
@@ -975,62 +975,62 @@ fun_head <- function(
 
 
 fun_tail <- function(
-    data1, 
-    n = 6, 
-    side = "l"
+data1, 
+n = 6, 
+side = "l"
 ){
-    # AIM
-    # as tail() but display the left or right head of big 2D objects
-    # ARGUMENTS
-    # data1: any object but more dedicated for matrix, data frame or table
-    # n: as in tail() but for for matrix, data frame or table, number of dimension to print (10 means 10 rows and columns)
-    # side: either "l" or "r" for the left or right side of the 2D object (only for matrix, data frame or table)
-    # BEWARE: other arguments of tail() not used
-    # RETURN
-    # the tail
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # obs1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:6], LETTERS[1:5])) ; obs1 ; fun_tail(obs1, 3, "r")
-    # DEBUGGING
-    # data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = n, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = side, options = c("l", "r"), length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
-        return(tail(data1, n))
-    }else{
-        obs.dim <- dim(data1)
-        row <- ifelse(obs.dim[1] < n, 1, obs.dim[1] - n + 1):obs.dim[1]
-        if(side == "l"){
-            col <- 1:ifelse(obs.dim[2] < n, obs.dim[2], n)
-        }
-        if(side == "r"){
-            col <- ifelse(obs.dim[2] < n, 1, obs.dim[2] - n + 1):obs.dim[2]
-        }
-        return(data1[row, col])
-    }
+# AIM
+# as tail() but display the left or right head of big 2D objects
+# ARGUMENTS
+# data1: any object but more dedicated for matrix, data frame or table
+# n: as in tail() but for for matrix, data frame or table, number of dimension to print (10 means 10 rows and columns)
+# side: either "l" or "r" for the left or right side of the 2D object (only for matrix, data frame or table)
+# BEWARE: other arguments of tail() not used
+# RETURN
+# the tail
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# obs1 = matrix(1:30, ncol = 5, dimnames = list(letters[1:6], LETTERS[1:5])) ; obs1 ; fun_tail(obs1, 3, "r")
+# DEBUGGING
+# data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = side, options = c("l", "r"), length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
+return(tail(data1, n))
+}else{
+obs.dim <- dim(data1)
+row <- ifelse(obs.dim[1] < n, 1, obs.dim[1] - n + 1):obs.dim[1]
+if(side == "l"){
+col <- 1:ifelse(obs.dim[2] < n, obs.dim[2], n)
+}
+if(side == "r"){
+col <- ifelse(obs.dim[2] < n, 1, obs.dim[2] - n + 1):obs.dim[2]
+}
+return(data1[row, col])
+}
 }
 
 
@@ -1038,12382 +1038,12393 @@ fun_tail <- function(
 
 
 fun_comp_1d <- function(data1, data2){
-    # AIM
-    # compare two 1D datasets (vector or factor or 1D table, or 1D matrix or 1D array) of the same class or not. Check and report in a list if the 2 datasets have:
-    # same class
-    # common elements
-    # common element names (except factors)
-    # common levels (factors only)
-    # ARGUMENTS
-    # data1: vector or factor or 1D table, or 1D matrix or 1D array
-    # data2: vector or factor or 1D table, or 1D matrix or 1D array
-    # RETURN
-    # a list containing:
-    # $same.class: logical. Are class identical?
-    # $class: class of the 2 datasets (NULL otherwise)
-    # $same.length: logical. Are number of elements identical?
-    # $length: number of elements in the 2 datasets (NULL otherwise)
-    # $same.levels: logical. Are levels identical? NULL if data1 and data2 are not factors
-    # $levels: levels of the 2 datasets if identical (NULL otherwise or NULL if data1 and data2 are not factors)
-    # $any.id.levels: logical. Is there any identical levels? (NULL if data1 and data2 are not factors)
-    # $same.levels.pos1: positions, in data1, of the levels identical in data2 (NULL otherwise or NULL if data1 and data2 are not factors)
-    # $same.levels.pos2: positions, in data2, of the levels identical in data1 (NULL otherwise or NULL if data1 and data2 are not factors)
-    # $same.levels.match1: positions, in data2, of the levels that match the levels in data1, as given by match(data1, data2) (NULL otherwise or NULL if data1 and data2 are not factors)
-    # $same.levels.match2: positions, in data1, of the levels that match the levels in data2, as given by match(data1, data2) (NULL otherwise or NULL if data1 and data2 are not factors)
-    # $common.levels: common levels between data1 and data2 (can be a subset of $levels or not). NULL if no common levels or if data1 and data2 are not factors
-    # $same.names: logical. Are element names identical? NULL if data1 and data2 have no names
-    # $name: name of elements of the 2 datasets if identical (NULL otherwise)
-    # $any.id.name: logical. Is there any element names identical ?
-    # $same.names.pos1: positions, in data1, of the element names identical in data2. NULL if no identical names
-    # $same.names.pos2: positions, in data2, of the elements names identical in data1. NULL if no identical names
-    # $same.names.match1: positions, in data2, of the names that match the names in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.names.match2: positions, in data1, of the names that match the names in data2, as given by match(data1, data2) (NULL otherwise)
-    # $common.names: common element names between data1 and data2 (can be a subset of $name or not). NULL if no common element names
-    # $any.id.element: logical. is there any identical elements ?
-    # $same.elements.pos1: positions, in data1, of the elements identical in data2. NULL if no identical elements
-    # $same.elements.pos2: positions, in data2, of the elements identical in data1. NULL if no identical elements
-    # $same.elements.match1: positions, in data2, of the elements that match the elements in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.elements.match2: positions, in data1, of the elements that match the elements in data2, as given by match(data1, data2) (NULL otherwise)
-    # $common.elements: common elements between data1 and data2. NULL if no common elements
-    # $same.order: logical. Are all elements in the same order? TRUE or FALSE if elements of data1 and data2 are identical but not necessary in the same order. NULL otherwise (different length for instance)
-    # $order1: order of all elements of data1. NULL if $same.order is FALSE
-    # $order2: order of all elements of data2. NULL if $same.order is FALSE
-    # $identical.object: logical. Are objects identical (kind of object, element names, content, including content order)?
-    # $identical.content: logical. Are content objects identical (identical elements, including order, excluding kind of object and element names)?
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # none
-    # EXAMPLES
-    # obs1 = 1:5 ; obs2 = 1:5 ; names(obs1) <- LETTERS[1:5] ; names(obs2) <- LETTERS[1:5] ; fun_comp_1d(obs1, obs2)
-    # obs1 = 1:5 ; obs2 = 1:5 ; names(obs1) <- LETTERS[1:5] ; fun_comp_1d(obs1, obs2)
-    # obs1 = 1:5 ; obs2 = 3:6 ; names(obs1) <- LETTERS[1:5] ; names(obs2) <- LETTERS[1:4] ; fun_comp_1d(obs1, obs2)
-    # obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[1:5]) ; fun_comp_1d(obs1, obs2)
-    # obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[10:11]) ; fun_comp_1d(obs1, obs2)
-    # obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[4:7]) ; fun_comp_1d(obs1, obs2)
-    # obs1 = factor(c(LETTERS[1:4], "E")) ; obs2 = factor(c(LETTERS[1:4], "F")) ; fun_comp_1d(obs1, obs2)
-    # obs1 = 1:5 ; obs2 = factor(LETTERS[1:5]) ; fun_comp_1d(obs1, obs2)
-    # obs1 = 1:5 ; obs2 = 1.1:6.1 ; fun_comp_1d(obs1, obs2)
-    # obs1 = as.table(1:5); obs2 = as.table(1:5) ; fun_comp_1d(obs1, obs2)
-    # obs1 = as.table(1:5); obs2 = 1:5 ; fun_comp_1d(obs1, obs2)
-    # DEBUGGING
-    # data1 = 1:5 ; data2 = 1:5 ; names(data1) <- LETTERS[1:5] ; names(data2) <- LETTERS[1:5] # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # argument checking
-    if( ! any(class(data1) %in% c("logical", "integer", "numeric", "character", "factor", "table"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A NON NULL VECTOR, FACTOR OR 1D TABLE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if(all(class(data1) %in% "table")){
-        if(length(dim(data1)) > 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A 1D TABLE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! any(class(data2) %in% c("logical", "integer", "numeric", "character", "factor", "table"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A NON NULL VECTOR, FACTOR OR 1D TABLE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if(all(class(data2) %in% "table")){
-        if(length(dim(data2)) > 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A 1D TABLE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
-    # end argument checking
-    # main code
-    same.class <- FALSE
-    class <- NULL
-    same.length <- FALSE
-    length <- NULL
-    same.levels <- NULL # not FALSE to deal with no factors
-    levels <- NULL
-    any.id.levels <- FALSE
-    same.levels.pos1 <- NULL
-    same.levels.pos2 <- NULL
-    same.levels.match1 <- NULL
-    same.levels.match2 <- NULL
-    common.levels <- NULL
-    same.names <- NULL # not FALSE to deal with absence of name
-    name <- NULL
-    any.id.name <- FALSE
-    same.names.pos1 <- NULL
-    same.names.pos2 <- NULL
-    same.names.match1 <- NULL
-    same.names.match2 <- NULL
-    common.names <- NULL
-    any.id.element <- FALSE
-    same.elements.pos1 <- NULL
-    same.elements.pos2 <- NULL
-    same.elements.match1 <- NULL
-    same.elements.match2 <- NULL
-    common.elements <- NULL
-    same.order <- NULL
-    order1 <- NULL
-    order2 <- NULL
-    identical.object <- FALSE
-    identical.content <- FALSE
-    if(identical(data1, data2)){
-        same.class <- TRUE
-        class <- class(data1)
-        same.length <- TRUE
-        length <- length(data1)
-        if(any(class(data1) %in% "factor")){
-            same.levels <- TRUE
-            levels <- levels(data1)
-            any.id.levels <- TRUE
-            same.levels.pos1 <- 1:length(levels(data1))
-            same.levels.pos2 <- 1:length(levels(data2))
-            same.levels.match1 <- 1:length(levels(data1))
-            same.levels.match2 <- 1:length(levels(data2))
-            common.levels <- levels(data1)
-        }
-        if( ! is.null(names(data1))){
-            same.names <- TRUE
-            name <- names(data1)
-            any.id.name <- TRUE
-            same.names.pos1 <- 1:length(data1)
-            same.names.pos2 <- 1:length(data2)
-            same.names.match1 <- 1:length(data1)
-            same.names.match2 <- 1:length(data2)
-            common.names <- names(data1)
-        }
-        any.id.element <- TRUE
-        same.elements.pos1 <- 1:length(data1)
-        same.elements.pos2 <- 1:length(data2)
-        same.elements.match1 <- 1:length(data1)
-        same.elements.match2 <- 1:length(data2)
-        common.elements <- data1
-        same.order <- TRUE
-        order1 <- order(data1)
-        order2 <- order(data2)
-        identical.object <- TRUE
-        identical.content <- TRUE
-    }else{
-        if(identical(class(data1), class(data2))){
-            same.class <- TRUE
-            class <- class(data1)
-        }
-        if(identical(length(data1), length(data2))){
-            same.length<- TRUE
-            length <- length(data1)
-        }
-        if(any(class(data1) %in% "factor") & any(class(data2) %in% "factor")){
-            if(identical(levels(data1), levels(data2))){
-                same.levels <- TRUE
-                levels <- levels(data1)
-            }else{
-                same.levels <- FALSE
-            }
-            if(any(levels(data1) %in% levels(data2))){
-                any.id.levels <- TRUE
-                same.levels.pos1 <- which(levels(data1) %in% levels(data2))
-                same.levels.match1 <- match(levels(data1), levels(data2))
-            }
-            if(any(levels(data2) %in% levels(data1))){
-                any.id.levels <- TRUE
-                same.levels.pos2 <- which(levels(data2) %in% levels(data1))
-                same.levels.match2 <- match(levels(data2), levels(data1))
-            }
-            if(any.id.levels == TRUE){
-                common.levels <- unique(c(levels(data1)[same.levels.pos1], levels(data2)[same.levels.pos2]))
-            }
-        }
-        if(any(class(data1) %in% "factor")){ # to compare content
-            data1 <- as.character(data1)
-        }
-        if(any(class(data2) %in% "factor")){ # to compare content
-            data2 <- as.character(data2)
-        }
-        if( ! (is.null(names(data1)) & is.null(names(data2)))){
-            if(identical(names(data1), names(data2))){
-                same.names <- TRUE
-                name <- names(data1)
-            }else{
-                same.names <- FALSE
-            }
-            if(any(names(data1) %in% names(data2))){
-                any.id.name <- TRUE
-                same.names.pos1 <- which(names(data1) %in% names(data2))
-                same.names.match1 <- match(names(data1), names(data2))
-            }
-            if(any(names(data2) %in% names(data1))){
-                any.id.name <- TRUE
-                same.names.pos2 <- which(names(data2) %in% names(data1))
-                same.names.match2 <- match(names(data2), names(data1))
-            }
-            if(any.id.name == TRUE){
-                common.names <- unique(c(names(data1)[same.names.pos1], names(data2)[same.names.pos2]))
-            }
-        }
-        names(data1) <- NULL # names solved -> to do not be disturbed by names
-        names(data2) <- NULL # names solved -> to do not be disturbed by names
-        if(any(data1 %in% data2)){
-            any.id.element <- TRUE
-            same.elements.pos1 <- which(data1 %in% data2)
-            same.elements.match1 <- match(data1, data2)
-        }
-        if(any(data2 %in% data1)){
-            any.id.element <- TRUE
-            same.elements.pos2 <- which(data2 %in% data1)
-            same.elements.match2 <- match(data2, data1)
-        }
-        if(any.id.element == TRUE){
-            common.elements <- unique(c(data1[same.elements.pos1], data2[same.elements.pos2]))
-        }
-        if(identical(data1, data2)){
-            identical.content <- TRUE
-            same.order <- TRUE
-        }else if(identical(sort(data1), sort(data2))){
-            same.order <- FALSE
-            order1 <- order(data1)
-            order2 <- order(data2)
-        }
-    }
-    output <- list(same.class = same.class, class = class, same.length = same.length, length = length, same.levels = same.levels, levels = levels, any.id.levels = any.id.levels, same.levels.pos1 = same.levels.pos1, same.levels.pos2 = same.levels.pos2, same.levels.match1 = same.levels.match1, same.levels.match2 = same.levels.match2, common.levels = common.levels, same.names = same.names, name = name, any.id.name = any.id.name, same.names.pos1 = same.names.pos1, same.names.pos2 = same.names.pos2, same.names.match1 = same.names.match1, same.names.match2 = same.names.match2, common.names = common.names, any.id.element = any.id.element, same.elements.pos1 = same.elements.pos1, same.elements.pos2 = same.elements.pos2, same.elements.match1 = same.elements.match1, same.elements.match2 = same.elements.match2, common.elements = common.elements, same.order = same.order, order1 = order1, order2 = order2, identical.object = identical.object, identical.content = identical.content)
-    return(output)
+# AIM
+# compare two 1D datasets (vector or factor or 1D table, or 1D matrix or 1D array) of the same class or not. Check and report in a list if the 2 datasets have:
+# same class
+# common elements
+# common element names (except factors)
+# common levels (factors only)
+# ARGUMENTS
+# data1: vector or factor or 1D table, or 1D matrix or 1D array
+# data2: vector or factor or 1D table, or 1D matrix or 1D array
+# RETURN
+# a list containing:
+# $same.class: logical. Are class identical?
+# $class: class of the 2 datasets (NULL otherwise)
+# $same.length: logical. Are number of elements identical?
+# $length: number of elements in the 2 datasets (NULL otherwise)
+# $same.levels: logical. Are levels identical? NULL if data1 and data2 are not factors
+# $levels: levels of the 2 datasets if identical (NULL otherwise or NULL if data1 and data2 are not factors)
+# $any.id.levels: logical. Is there any identical levels? (NULL if data1 and data2 are not factors)
+# $same.levels.pos1: positions, in data1, of the levels identical in data2 (NULL otherwise or NULL if data1 and data2 are not factors)
+# $same.levels.pos2: positions, in data2, of the levels identical in data1 (NULL otherwise or NULL if data1 and data2 are not factors)
+# $same.levels.match1: positions, in data2, of the levels that match the levels in data1, as given by match(data1, data2) (NULL otherwise or NULL if data1 and data2 are not factors)
+# $same.levels.match2: positions, in data1, of the levels that match the levels in data2, as given by match(data1, data2) (NULL otherwise or NULL if data1 and data2 are not factors)
+# $common.levels: common levels between data1 and data2 (can be a subset of $levels or not). NULL if no common levels or if data1 and data2 are not factors
+# $same.names: logical. Are element names identical? NULL if data1 and data2 have no names
+# $name: name of elements of the 2 datasets if identical (NULL otherwise)
+# $any.id.name: logical. Is there any element names identical ?
+# $same.names.pos1: positions, in data1, of the element names identical in data2. NULL if no identical names
+# $same.names.pos2: positions, in data2, of the elements names identical in data1. NULL if no identical names
+# $same.names.match1: positions, in data2, of the names that match the names in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.names.match2: positions, in data1, of the names that match the names in data2, as given by match(data1, data2) (NULL otherwise)
+# $common.names: common element names between data1 and data2 (can be a subset of $name or not). NULL if no common element names
+# $any.id.element: logical. is there any identical elements ?
+# $same.elements.pos1: positions, in data1, of the elements identical in data2. NULL if no identical elements
+# $same.elements.pos2: positions, in data2, of the elements identical in data1. NULL if no identical elements
+# $same.elements.match1: positions, in data2, of the elements that match the elements in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.elements.match2: positions, in data1, of the elements that match the elements in data2, as given by match(data1, data2) (NULL otherwise)
+# $common.elements: common elements between data1 and data2. NULL if no common elements
+# $same.order: logical. Are all elements in the same order? TRUE or FALSE if elements of data1 and data2 are identical but not necessary in the same order. NULL otherwise (different length for instance)
+# $order1: order of all elements of data1. NULL if $same.order is FALSE
+# $order2: order of all elements of data2. NULL if $same.order is FALSE
+# $identical.object: logical. Are objects identical (kind of object, element names, content, including content order)?
+# $identical.content: logical. Are content objects identical (identical elements, including order, excluding kind of object and element names)?
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# none
+# EXAMPLES
+# obs1 = 1:5 ; obs2 = 1:5 ; names(obs1) <- LETTERS[1:5] ; names(obs2) <- LETTERS[1:5] ; fun_comp_1d(obs1, obs2)
+# obs1 = 1:5 ; obs2 = 1:5 ; names(obs1) <- LETTERS[1:5] ; fun_comp_1d(obs1, obs2)
+# obs1 = 1:5 ; obs2 = 3:6 ; names(obs1) <- LETTERS[1:5] ; names(obs2) <- LETTERS[1:4] ; fun_comp_1d(obs1, obs2)
+# obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[1:5]) ; fun_comp_1d(obs1, obs2)
+# obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[10:11]) ; fun_comp_1d(obs1, obs2)
+# obs1 = factor(LETTERS[1:5]) ; obs2 = factor(LETTERS[4:7]) ; fun_comp_1d(obs1, obs2)
+# obs1 = factor(c(LETTERS[1:4], "E")) ; obs2 = factor(c(LETTERS[1:4], "F")) ; fun_comp_1d(obs1, obs2)
+# obs1 = 1:5 ; obs2 = factor(LETTERS[1:5]) ; fun_comp_1d(obs1, obs2)
+# obs1 = 1:5 ; obs2 = 1.1:6.1 ; fun_comp_1d(obs1, obs2)
+# obs1 = as.table(1:5); obs2 = as.table(1:5) ; fun_comp_1d(obs1, obs2)
+# obs1 = as.table(1:5); obs2 = 1:5 ; fun_comp_1d(obs1, obs2)
+# DEBUGGING
+# data1 = 1:5 ; data2 = 1:5 ; names(data1) <- LETTERS[1:5] ; names(data2) <- LETTERS[1:5] # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# argument checking
+if( ! any(class(data1) %in% c("logical", "integer", "numeric", "character", "factor", "table"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A NON NULL VECTOR, FACTOR OR 1D TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(all(class(data1) %in% "table")){
+if(length(dim(data1)) > 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A 1D TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
 }
-
-
-######## fun_comp_2d() #### comparison of two 2D datasets (row & col names, dimensions, etc.)
-
-
-fun_comp_2d <- function(data1, data2){
-    # AIM
-    # compare two 2D datasets of the same class or not. Check and report in a list if the 2 datasets have:
-    # same class
-    # common row names
-    # common column names
-    # same row number
-    # same column number
-    # potential identical rows between the 2 datasets
-    # potential identical columns between the 2 datasets
-    # WARNINGS
-    # For data frames: content are compared after conversion of content into characters. This means that the comparison of the content of data frame, either row to row, or column to column, does not take into account the mode in the different columns. This concern the results in $any.id.row, $same.row.pos1, $same.row.pos2, $same.row.match1, $same.row.match2, $any.id.col, $same.row.col1, $same.row.col2, $same.col.match1, $same.col.match2 and $identical.content result
-    # "TOO BIG FOR EVALUATION" returned in $same.row.pos1, $same.row.pos2, $same.row.match1 and $same.row.match2 when nrow(data1) * nrow(data2) > 1e6 and $any.id.row remains NULL
-    # "TOO BIG FOR EVALUATION" returned in $same.row.col1, $same.row.col2, $same.col.match1 and $same.col.match2 when ncol(data1) * ncol(data2) > 1e6 and $any.id.col remains NULL
-    # ARGUMENTS
-    # data1: matrix, data frame or table
-    # data2: matrix, data frame or table
-    # RETURN
-    # a list containing:
-    # $same.class: logical. Are class identical ?
-    # $class: classes of the 2 datasets (NULL otherwise)
-    # $same.dim: logical. Are dimension identical ?
-    # $dim: dimension of the 2 datasets (NULL otherwise)
-    # $same.row.nb: logical. Are number of rows identical ?
-    # $row.nb: nb of rows of the 2 datasets if identical (NULL otherwise)
-    # $same.col.nb: logical. Are number of columns identical ?
-    # $col.nb: nb of columns of the 2 datasets if identical (NULL otherwise)
-    # $same.row.name: logical. Are row names identical ? NULL if no row names in the two 2D datasets
-    # $row.name: name of rows of the 2 datasets if identical (NULL otherwise)
-    # $any.id.row.name: logical. Is there any row names identical ? NULL if no row names in the two 2D datasets
-    # $same.row.names.pos1: positions, in data1, of the row names identical in data2
-    # $same.row.names.pos2: positions, in data2, of the row names identical in data1
-    # $same.row.names.match1: positions, in data2, of the row names that match the row names in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.row.names.match2: positions, in data1, of the row names that match the row names in data2, as given by match(data1, data2) (NULL otherwise)
-    # $common.row.names: common row names between data1 and data2 (can be a subset of $name or not). NULL if no common row names
-    # $same.col.name: logical. Are column names identical ? NULL if no col names in the two 2D datasets
-    # $col.name: name of columns of the 2 datasets if identical (NULL otherwise)
-    # $any.id.col.name: logical. Is there any column names identical ? NULL if no col names in the two 2D datasets
-    # $same.col.names.pos1: positions, in data1, of the column names identical in data2
-    # $same.col.names.pos2: positions, in data2, of the column names identical in data1
-    # $same.col.names.match1: positions, in data2, of the column names that match the column names in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.col.names.match2: positions, in data1, of the column names that match the column names in data2, as given by match(data1, data2) (NULL otherwise)
-    # $common.col.names: common column names between data1 and data2 (can be a subset of $name or not). NULL if no common column names
-    # $any.id.row: logical. is there identical rows (not considering row names)? NULL if nrow(data1) * nrow(data2) > 1e10
-    # $same.row.pos1: positions, in data1, of the rows identical in data2 (not considering row names). Return "TOO BIG FOR EVALUATION" if nrow(data1) * nrow(data2) > 1e10
-    # $same.row.pos2: positions, in data2, of the rows identical in data1 (not considering row names). Return "TOO BIG FOR EVALUATION" if nrow(data1) * nrow(data2) > 1e10
-    # $same.row.match1: positions, in data2, of the rows that match the rows in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.row.match2: positions, in data1, of the rows that match the rows in data2, as given by match(data1, data2) (NULL otherwise)
-    # $any.id.col: logical. is there identical columns (not considering column names)? NULL if ncol(data1) * ncol(data2) > 1e10
-    # $same.col.pos1: position in data1 of the cols identical in data2 (not considering column names). Return "TOO BIG FOR EVALUATION" if ncol(data1) * ncol(data2) > 1e10
-    # $same.col.pos2: position in data2 of the cols identical in data1 (not considering column names). Return "TOO BIG FOR EVALUATION" if ncol(data1) * ncol(data2) > 1e10
-    # $same.col.match1: positions, in data2, of the columns that match the columns in data1, as given by match(data1, data2) (NULL otherwise)
-    # $same.row.match2: positions, in data1, of the columns that match the columns in data2, as given by match(data1, data2) (NULL otherwise)
-    # $identical.object: logical. Are objects identical (including row & column names)?
-    # $identical.content: logical. Are content objects identical (identical excluding row & column names)?
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # none
-    # EXAMPLES
-    # obs1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = as.data.frame(matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])), stringsAsFactors = TRUE) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
-    # obs1 = matrix(101:110, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
-    # large matrices
-    # obs1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; obs2 = matrix(as.integer((1:1e6)+1e6/5), ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; head(obs1) ; head(obs2) ; fun_comp_2d(obs1, obs2)
-    # WARNING: when comparing content (rows, columns, or total), double and integer data are considered as different -> double(1) != integer(1)
-    # obs1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; obs2 = matrix((1:1e6)+1e6/5, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; head(obs1) ; head(obs2) ; fun_comp_2d(obs1, obs2)
-    # Matrices: same row conten tand same row names
-    # obs1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4]))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
-    # Matrices: same row content but not same row names -> works: same content is identified
-    # obs1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("x", "z", "y"), c(LETTERS[1:2], "k", LETTERS[5:4]))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
-    # obs1 = t(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = t(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
-    # Data frames: same row content and same row names, not same mode between columns
-    # obs1 = as.data.frame(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = as.data.frame(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1[, 5] <- as.character(obs1[, 5]) ; obs2[, 5] <- as.character(obs2[, 5]) ; obs1 ; obs2 ; str(obs1) ; str(obs2) ; fun_comp_2d(obs1, obs2)
-    # Data frames: same row content but not same row names -> works: same content is identified
-    # obs1 = as.data.frame(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = as.data.frame(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("x", "z", "y"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1[, 5] <- as.character(obs1[, 5]) ; obs2[, 5] <- as.character(obs2[, 5]) ; obs1 ; obs2 ; str(obs1) ; str(obs2) ; fun_comp_2d(obs1, obs2)
-    # DEBUGGING
-    # data1 = matrix(1:10, ncol = 5) ; data2 = matrix(1:10, ncol = 5) # for function debugging
-    # data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5) # for function debugging
-    # data1 = matrix(1:15, byrow = TRUE, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # data1 = matrix(1:15, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # data1 = matrix(1:15, ncol = 5, dimnames = list(paste0("A", letters[1:3]), LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # data1 = matrix(1:15, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:12, ncol = 4, dimnames = list(letters[1:3], LETTERS[1:4])) # for function debugging
-    # data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(101:110, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
-    # data1 = data.frame(a = 1:3, b= letters[1:3], row.names = LETTERS[1:3], stringsAsFactors = TRUE) ; data2 = data.frame(A = 1:3, B= letters[1:3], stringsAsFactors = TRUE) # for function debugging
-    # data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = as.data.frame(matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])), stringsAsFactors = TRUE) # for function debugging
-    # data1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4]))) # for function debugging
-    # data1 = table(Exp1 = c("A", "A", "A", "B", "B", "B"), Exp2 = c("A1", "B1", "A1", "C1", "C1", "B1")) ; data2 = data.frame(A = 1:3, B= letters[1:3], stringsAsFactors = TRUE) # for function debugging
-    # data1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; data2 = matrix((1:1e6)+1e6/5, ncol = 5, dimnames = list(NULL, LETTERS[1:5]))
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # argument checking
-    if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A MATRIX, DATA FRAME OR TABLE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (any(class(data2) %in% c("data.frame", "table")) | all(class(data2) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data2) %in% c("matrix", "data.frame", "table"))
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A MATRIX, DATA FRAME OR TABLE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
-    # end argument checking
-    # main code
-    same.class <- NULL
-    class <- NULL
-    same.dim <- NULL
-    dim <- NULL
-    same.row.nb <- NULL
-    row.nb <- NULL
-    same.col.nb <- NULL
-    col.nb <- NULL
-    same.row.name <- NULL
-    row.name <- NULL
-    any.id.row.name <- NULL
-    same.row.names.pos1 <- NULL
-    same.row.names.pos2 <- NULL
-    same.row.names.match1 <- NULL
-    same.row.names.match2 <- NULL
-    common.row.names <- NULL
-    same.col.name <- NULL
-    any.id.col.name <- NULL
-    same.col.names.pos1 <- NULL
-    same.col.names.pos2 <- NULL
-    same.col.names.match1 <- NULL
-    same.col.names.match2 <- NULL
-    common.col.names <- NULL
-    col.name <- NULL
-    any.id.row <- NULL
-    same.row.pos1 <- NULL
-    same.row.pos2 <- NULL
-    same.row.match1 <- NULL
-    same.row.match2 <- NULL
-    any.id.col <- NULL
-    same.col.pos1 <- NULL
-    same.col.pos2 <- NULL
-    same.col.match1 <- NULL
-    same.col.match2 <- NULL
-    identical.object <- NULL
-    identical.content <- NULL
-    if(identical(data1, data2) & (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
-        same.class <- TRUE
-        class <- class(data1)
-        same.dim <- TRUE
-        dim <- dim(data1)
-        same.row.nb <- TRUE
-        row.nb <- nrow(data1)
-        same.col.nb <- TRUE
-        col.nb <- ncol(data1)
-        same.row.name <- TRUE
-        row.name <- dimnames(data1)[[1]]
-        any.id.row.name <- TRUE
-        same.row.names.pos1 <- 1:row.nb
-        same.row.names.pos2 <- 1:row.nb
-        same.row.names.match1 <- 1:row.nb
-        same.row.names.match2 <- 1:row.nb
-        common.row.names <- dimnames(data1)[[1]]
-        same.col.name <- TRUE
-        col.name <- dimnames(data1)[[2]]
-        any.id.col.name <- TRUE
-        same.col.names.pos1 <- 1:col.nb
-        same.col.names.pos2 <- 1:col.nb
-        same.col.names.match1 <- 1:col.nb
-        same.col.names.match2 <- 1:col.nb
-        common.col.names <- dimnames(data1)[[2]]
-        any.id.row <- TRUE
-        same.row.pos1 <- 1:row.nb
-        same.row.pos2 <- 1:row.nb
-        same.row.match1 <- 1:row.nb
-        same.row.match2 <- 1:row.nb
-        any.id.col <- TRUE
-        same.col.pos1 <- 1:col.nb
-        same.col.pos2 <- 1:col.nb
-        same.col.match1 <- 1:col.nb
-        same.col.match2 <- 1:col.nb
-        identical.object <- TRUE
-        identical.content <- TRUE
-    }else{
-        identical.object <- FALSE
-        if(all(class(data1) == "table") & length(dim(data1)) == 1L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT IS A 1D TABLE. USE THE fun_comp_1d FUNCTION")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(all(class(data2) == "table") & length(dim(data2)) == 1L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT IS A 1D TABLE. USE THE fun_comp_1d FUNCTION")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! identical(class(data1), class(data2))){
-            same.class <- FALSE
-        }else if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 AND data2 ARGUMENTS MUST BE EITHER MATRIX, DATA FRAME OR TABLE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            same.class <- TRUE
-            class <- class(data1)
-        }
-        if( ! identical(dim(data1), dim(data2))){
-            same.dim <- FALSE
-        }else{
-            same.dim <- TRUE
-            dim <- dim(data1)
-        }
-        if( ! identical(nrow(data1), nrow(data2))){
-            same.row.nb <- FALSE
-        }else{
-            same.row.nb <- TRUE
-            row.nb <- nrow(data1)
-        }
-        if( ! identical(ncol(data1), ncol(data2))){
-            same.col.nb <- FALSE
-        }else{
-            same.col.nb <- TRUE
-            col.nb <- ncol(data1)
-        }
-        # row and col names
-        if(is.null(dimnames(data1)) & is.null(dimnames(data2))){
-            same.row.name <- NULL # but already NULL
-            same.col.name <- NULL # but already NULL
-            # other row names param remain NULL
-        }else if((is.null(dimnames(data1)) & ! is.null(dimnames(data2))) | ( ! is.null(dimnames(data1)) & is.null(dimnames(data2)))){
-            same.row.name <- FALSE
-            same.col.name <- FALSE
-            any.id.row.name <- FALSE
-            any.id.col.name <- FALSE
-            # other row names param remain NULL
-        }else{
-            # row names
-            if(is.null(dimnames(data1)[[1]]) & is.null(dimnames(data2)[[1]])){
-                same.row.name <- NULL # but already NULL
-                # other row names param remain NULL
-            }else if((is.null(dimnames(data1)[[1]]) & ! is.null(dimnames(data2)[[1]])) | ( ! is.null(dimnames(data1)[[1]]) & is.null(dimnames(data2)[[1]]))){
-                same.row.name <- FALSE
-                any.id.row.name <- FALSE
-                # other row names param remain NULL
-            }else if(identical(dimnames(data1)[[1]], dimnames(data2)[[1]])){
-                same.row.name <- TRUE
-                row.name <- dimnames(data1)[[1]]
-                any.id.row.name <- TRUE
-                same.row.names.pos1 <- 1:nrow(data1)
-                same.row.names.pos2 <- 1:nrow(data1)
-                same.row.names.match1 <- 1:nrow(data1)
-                same.row.names.match2 <- 1:nrow(data1)
-                common.row.names <- dimnames(data1)[[1]]
-            }else{
-                same.row.name <- FALSE
-                any.id.row.name <- FALSE
-                if(any(dimnames(data1)[[1]] %in% dimnames(data2)[[1]])){
-                    any.id.row.name <- TRUE
-                    same.row.names.pos1 <- which(dimnames(data1)[[1]] %in% dimnames(data2)[[1]])
-                    same.row.names.match1 <- match(dimnames(data1)[[1]], dimnames(data2)[[1]])
-                }
-                if(any(dimnames(data2)[[1]] %in% dimnames(data1)[[1]])){
-                    any.id.row.name <- TRUE
-                    same.row.names.pos2 <- which(dimnames(data2)[[1]] %in% dimnames(data1)[[1]])
-                    same.row.names.match2 <- match(dimnames(data2)[[1]], dimnames(data1)[[1]])
-                }
-                if(any.id.row.name == TRUE){
-                    common.row.names <- unique(c(dimnames(data1)[[1]][same.row.names.pos1], dimnames(data2)[[1]][same.row.names.pos2]))
-                }
-            }
-            # col names
-            if(is.null(dimnames(data1)[[2]]) & is.null(dimnames(data2)[[2]])){
-                same.col.name <- NULL # but already NULL
-                # other col names param remain NULL
-            }else if((is.null(dimnames(data1)[[2]]) & ! is.null(dimnames(data2)[[2]])) | ( ! is.null(dimnames(data1)[[2]]) & is.null(dimnames(data2)[[2]]))){
-                same.col.name <- FALSE
-                any.id.col.name <- FALSE
-                # other col names param remain NULL
-            }else if(identical(dimnames(data1)[[2]], dimnames(data2)[[2]])){
-                same.col.name <- TRUE
-                col.name <- dimnames(data1)[[2]]
-                any.id.col.name <- TRUE
-                same.col.names.pos1 <- 1:ncol(data1)
-                same.col.names.pos2 <- 1:ncol(data1)
-                same.col.names.match1 <- 1:ncol(data1)
-                same.col.names.match2 <- 1:ncol(data1)
-                common.col.names <- dimnames(data1)[[2]]
-            }else{
-                same.col.name <- FALSE
-                any.id.col.name <- FALSE
-                if(any(dimnames(data1)[[2]] %in% dimnames(data2)[[2]])){
-                    any.id.col.name <- TRUE
-                    same.col.names.pos1 <- which(dimnames(data1)[[2]] %in% dimnames(data2)[[2]])
-                    same.col.names.match1 <- match(dimnames(data1)[[2]], dimnames(data2)[[2]])
-                }
-                if(any(dimnames(data2)[[2]] %in% dimnames(data1)[[2]])){
-                    any.id.col.name <- TRUE
-                    same.col.names.pos2 <- which(dimnames(data2)[[2]] %in% dimnames(data1)[[2]])
-                    same.col.names.match2 <- match(dimnames(data2)[[2]], dimnames(data1)[[2]])
-                }
-                if(any.id.col.name == TRUE){
-                    common.col.names <- unique(c(dimnames(data1)[[2]][same.col.names.pos1], dimnames(data2)[[2]][same.col.names.pos2]))
-                }
-            }
-        }
-        # identical row and col content
-        if(all(class(data1) == "table")){
-            data1 <- as.data.frame(matrix(data1, ncol = ncol(data1)), stringsAsFactors = FALSE) # conversion of table into data frame to facilitate inter class comparison
-        }else if(all(class(data1) %in% c("matrix", "array"))){
-            data1 <- as.data.frame(data1, stringsAsFactors = FALSE) # conversion of matrix into data frame to facilitate inter class comparison
-        }else if(all(class(data1) == "data.frame")){
-            # data1 <- data.frame(lapply(data1, as.character), stringsAsFactors = FALSE) # conversion of columns into characters
-        }
-        if(all(class(data2) == "table")){
-            data2 <- as.data.frame(matrix(data2, ncol = ncol(data2)), stringsAsFactors = FALSE) # conversion of table into data frame to facilitate inter class comparison
-        }else if(all(class(data2) %in% c("matrix", "array"))){
-            data2 <- as.data.frame(data2, stringsAsFactors = FALSE) # conversion of matrix into data frame to facilitate inter class comparison
-        }else if(all(class(data2) == "data.frame")){
-            # data2 <- data.frame(lapply(data2, as.character), stringsAsFactors = FALSE) # conversion of columns into characters
-        }
-        row.names(data1) <- paste0("A", 1:nrow(data1))
-        row.names(data2) <- paste0("A", 1:nrow(data2))
-        if(same.col.nb == TRUE){ # because if not the same col nb, the row cannot be identical
-            if(all(sapply(data1, FUN = typeof) == "integer") & all(sapply(data2, FUN = typeof) == "integer") & as.double(nrow(data1)) * nrow(data2) <= 1e10){ # fast method for integers (thus not data frames). as.double(nrow(data1)) to prevent integer overflow because R is 32 bits for integers
-                tempo1 <- c(as.data.frame(t(data1), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
-                tempo2 <- c(as.data.frame(t(data2), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
-                same.row.pos1 <- which(tempo1 %in% tempo2)
-                same.row.pos2 <- which(tempo2 %in% tempo1)
-                same.row.match1 <- match(tempo1, tempo2)
-                same.row.match2 <- match(tempo2, tempo1)
-            }else if(as.double(nrow(data1)) * nrow(data2) <= 1e6){ # as.double(nrow(data1)) to prevent integer overflow because R is 32 bits for integers
-                # inactivated because I would like to keep the mode during comparisons
-                # if(col.nb <= 10){ # if ncol is not to big, the t() should not be that long
-                # tempo1 <- c(as.data.frame(t(data1), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
-                # tempo2 <- c(as.data.frame(t(data2), stringsAsFactors = FALSE)) # conversion into list. 
-                # same.row.pos1 <- which(tempo1 %in% tempo2)
-                # same.row.pos2 <- which(tempo2 %in% tempo1)
-                # same.row.match1 <- match(tempo1, tempo2)
-                # same.row.match2 <- match(tempo2, tempo1)
-                # }else{
-                # very long computation
-                same.row.pos1 <- logical(length = nrow(data1)) # FALSE by default
-                same.row.pos1[] <- FALSE # security
-                same.row.pos2 <- logical(length = nrow(data2)) # FALSE by default
-                same.row.pos2[] <- FALSE # security
-                same.row.match1 <- rep(NA, nrow(data1))
-                same.row.match2 <- rep(NA, nrow(data2))
-                for(i3 in 1:nrow(data1)){
-                    for(i4 in 1:nrow(data2)){
-                        tempo1 <- data1[i3, ]
-                        tempo2 <- data2[i4, ]
-                        rownames(tempo1) <- NULL # to have same row and column names
-                        colnames(tempo1) <- NULL # to have same row and column names
-                        rownames(tempo2) <- NULL # to have same row and column names
-                        colnames(tempo2) <- NULL # to have same row and column names
-                        if(identical(tempo1, tempo2)){
-                            same.row.pos1[i3] <- TRUE
-                            same.row.pos2[i4] <- TRUE
-                            same.row.match1[i3] <- i4
-                            same.row.match2[i4] <- i3
-                        }
-                    }
-                }
-                same.row.pos1 <- which(same.row.pos1)
-                same.row.pos2 <- which(same.row.pos2)
-                # }
-            }else{
-                same.row.pos1 <- "TOO BIG FOR EVALUATION"
-                same.row.pos2 <- "TOO BIG FOR EVALUATION"
-                same.row.match1 <- "TOO BIG FOR EVALUATION"
-                same.row.match2 <- "TOO BIG FOR EVALUATION"
-            }
-            
-            names(same.row.pos1) <- NULL
-            names(same.row.pos2) <- NULL
-            if(all(is.na(same.row.pos1))){
-                same.row.pos1 <- NULL
-            }else{
-                same.row.pos1 <- same.row.pos1[ ! is.na(same.row.pos1)]
-                any.id.row <- TRUE
-            }
-            if(all(is.na(same.row.pos2))){
-                same.row.pos2 <- NULL
-            }else{
-                same.row.pos2 <- same.row.pos2[ ! is.na(same.row.pos2)]
-                any.id.row <- TRUE
-            }
-            if(is.null(same.row.pos1) & is.null(same.row.pos2)){
-                any.id.row <- FALSE
-            }else if(length(same.row.pos1) == 0L & length(same.row.pos2) == 0L){
-                any.id.row <- FALSE
-            }else if(all(same.row.pos1 == "TOO BIG FOR EVALUATION") & all(same.row.pos2 == "TOO BIG FOR EVALUATION")){
-                any.id.row <- NULL
-            }
-        }else{
-            any.id.row <- FALSE
-            # same.row.pos1 and 2 remain NULL
-        }
-        if(same.row.nb == TRUE){ # because if not the same row nb, the col cannot be identical
-            if(as.double(ncol(data1)) * ncol(data2) <= 1e10){ # comparison of data frame columns is much easier than rows because no need to use t() before converting to list for fast comparison. as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
-                # if(all(sapply(data1, FUN = typeof) == "integer") & all(sapply(data2, FUN = typeof) == "integer") & as.double(ncol(data1)) * ncol(data2) <= 1e10){ # fast method for integers (thus not data frames). as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
-                tempo1 <- c(data1)
-                tempo2 <- c(data2)
-                same.col.pos1 <- which(tempo1 %in% tempo2)
-                same.col.pos2 <- which(tempo2 %in% tempo1)
-                same.col.match1 <- match(tempo1, tempo2)
-                same.col.match2 <- match(tempo2, tempo1)
-                # }else if(as.double(ncol(data1)) * ncol(data2) <= 1e6){ # as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
-                # same.col.pos1 <- logical(length = ncol(data1)) # FALSE by default
-                # same.col.pos1[] <- FALSE # security
-                # same.col.pos2 <- logical(length = ncol(data2)) # FALSE by default
-                # same.col.pos2[] <- FALSE # security
-                # same.col.match1 <- rep(NA, ncol(data1))
-                # same.col.match2 <- rep(NA, ncol(data2))
-                # for(i3 in 1:ncol(data1)){
-                # for(i4 in 1:ncol(data2)){
-                # if(identical(data1[ , i3], data2[ , i4])){
-                # same.col.pos1[i3] <- TRUE
-                # same.col.pos2[i4] <- TRUE
-                # same.col.match1[i3] <- i4
-                # same.col.match2[i4] <- i3
-                # }
-                # }
-                # }
-                # same.col.pos1 <- which(same.col.pos1)
-                # same.col.pos2 <- which(same.col.pos2)
-            }else{
-                same.col.pos1 <- "TOO BIG FOR EVALUATION"
-                same.col.pos2 <- "TOO BIG FOR EVALUATION"
-            }
-            names(same.col.pos1) <- NULL
-            names(same.col.pos2) <- NULL
-            if(all(is.na(same.col.pos1))){
-                same.col.pos1 <- NULL
-            }else{
-                same.col.pos1 <- same.col.pos1[ ! is.na(same.col.pos1)]
-                any.id.col <- TRUE
-            }
-            if(all(is.na(same.col.pos2))){
-                same.col.pos2 <- NULL
-            }else{
-                same.col.pos2 <- same.col.pos2[ ! is.na(same.col.pos2)]
-                any.id.col <- TRUE
-            }
-            if(is.null(same.col.pos1) & is.null(same.col.pos2)){
-                any.id.col <- FALSE
-            }else if(length(same.col.pos1) == 0L & length(same.col.pos2) == 0L){
-                any.id.col <- FALSE
-            }else if(all(same.col.pos1 == "TOO BIG FOR EVALUATION") & all(same.col.pos2 == "TOO BIG FOR EVALUATION")){
-                any.id.col <- NULL
-            }
-        }else{
-            any.id.col <- FALSE
-            # same.col.pos1 and 2 remain NULL
-        }
-        if(same.dim == TRUE){
-            names(data1) <- NULL
-            row.names(data1) <- NULL
-            names(data2) <- NULL
-            row.names(data2) <- NULL
-            if(identical(data1, data2)){
-                identical.content <- TRUE
-            }else{
-                identical.content <- FALSE
-            }
-        }else{
-            identical.content <- FALSE
-        }
-    }
-    output <- list(same.class = same.class, class = class, same.dim = same.dim, dim = dim, same.row.nb = same.row.nb, row.nb = row.nb, same.col.nb = same.col.nb , col.nb = col.nb, same.row.name = same.row.name, row.name = row.name, any.id.row.name = any.id.row.name, same.row.names.pos1 = same.row.names.pos1, same.row.names.pos2 = same.row.names.pos2, same.row.names.match1 = same.row.names.match1, same.row.names.match2 = same.row.names.match2, common.row.names = common.row.names, same.col.name = same.col.name, col.name = col.name,any.id.col.name = any.id.col.name, same.col.names.pos1 = same.col.names.pos1, same.col.names.pos2 = same.col.names.pos2, same.col.names.match1 = same.col.names.match1, same.col.names.match2 = same.col.names.match2, common.col.names = common.col.names, any.id.row = any.id.row, same.row.pos1 = same.row.pos1, same.row.pos2 = same.row.pos2, same.row.match1 = same.row.match1, same.row.match2 = same.row.match2, any.id.col = any.id.col, same.col.pos1 = same.col.pos1, same.col.pos2 = same.col.pos2, same.col.match1 = same.col.match1, same.col.match2 = same.col.match2, identical.object = identical.object, identical.content = identical.content)
-    return(output)
 }
-
-
-######## fun_comp_list() #### comparison of two lists
-
-
-fun_comp_list <- function(data1, data2){
-    # AIM
-    # compare two lists. Check and report in a list if the 2 datasets have:
-    # same length
-    # common names
-    # common compartments
-    # ARGUMENTS
-    # data1: list
-    # data2: list
-    # RETURN
-    # a list containing:
-    # $same.length: logical. Are number of elements identical?
-    # $length: number of elements in the 2 datasets (NULL otherwise)
-    # $same.names: logical. Are element names identical ?
-    # $name: name of elements of the 2 datasets if identical (NULL otherwise)
-    # $any.id.name: logical. Is there any element names identical ?
-    # $same.names.pos1: positions, in data1, of the element names identical in data2
-    # $same.names.pos2: positions, in data2, of the compartment names identical in data1
-    # $any.id.compartment: logical. is there any identical compartments ?
-    # $same.compartment.pos1: positions, in data1, of the compartments identical in data2
-    # $same.compartment.pos2: positions, in data2, of the compartments identical in data1
-    # $identical.object: logical. Are objects identical (kind of object, compartment names and content)?
-    # $identical.content: logical. Are content objects identical (identical compartments excluding compartment names)?
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # none
-    # EXAMPLES
-    # obs1 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; obs2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; fun_comp_list(obs1, obs2)
-    # obs1 = list(1:5, LETTERS[1:2]) ; obs2 = list(a = 1:5, b = LETTERS[1:2]) ; fun_comp_list(obs1, obs2)
-    # obs1 = list(b = 1:5, c = LETTERS[1:2]) ; obs2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; fun_comp_list(obs1, obs2)
-    # obs1 = list(b = 1:5, c = LETTERS[1:2]) ; obs2 = list(LETTERS[5:9], matrix(1:6), 1:5) ; fun_comp_list(obs1, obs2)
-    # DEBUGGING
-    # data1 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; data2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) # for function debugging
-    # data1 = list(a = 1:5, b = LETTERS[1:2]) ; data2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # argument checking
-    if( ! any(class(data1) %in% "list")){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A LIST")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! any(class(data2) %in% "list")){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A LIST")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
-    # end argument checking
-    # main code
-    same.length <- NULL
-    length <- NULL
-    same.names <- NULL
-    name <- NULL
-    any.id.name <- NULL
-    same.names.pos1 <- NULL
-    same.names.pos2 <- NULL
-    any.id.compartment <- NULL
-    same.compartment.pos1 <- NULL
-    same.compartment.pos2 <- NULL
-    identical.object <- NULL
-    identical.content <- NULL
-    if(identical(data1, data2)){
-        same.length <- TRUE
-        length <- length(data1)
-        if( ! is.null(names(data1))){
-            same.names <- TRUE
-            name <- names(data1)
-            any.id.name <- TRUE
-            same.names.pos1 <- 1:length(data1)
-            same.names.pos2 <- 1:length(data2)
-        }
-        any.id.compartment <- TRUE
-        same.compartment.pos1 <- 1:length(data1)
-        same.compartment.pos2 <- 1:length(data2)
-        identical.object <- TRUE
-        identical.content <- TRUE
-    }else{
-        identical.object <- FALSE
-        if( ! identical(length(data1), length(data2))){
-            same.length<- FALSE
-        }else{
-            same.length<- TRUE
-            length <- length(data1)
-        }
-        if( ! (is.null(names(data1)) & is.null(names(data2)))){
-            if( ! identical(names(data1), names(data2))){
-                same.names <- FALSE
-            }else{
-                same.names <- TRUE
-                name <- names(data1)
-            }
-            any.id.name <- FALSE
-            if(any(names(data1) %in% names(data2))){
-                any.id.name <- TRUE
-                same.names.pos1 <- which(names(data1) %in% names(data2))
-            }
-            if(any(names(data2) %in% names(data1))){
-                any.id.name <- TRUE
-                same.names.pos2 <- which(names(data2) %in% names(data1))
-            }
-        }
-        names(data1) <- NULL
-        names(data2) <- NULL
-        any.id.compartment <- FALSE
-        if(any(data1 %in% data2)){
-            any.id.compartment <- TRUE
-            same.compartment.pos1 <- which(data1 %in% data2)
-        }
-        if(any(data2 %in% data1)){
-            any.id.compartment <- TRUE
-            same.compartment.pos2 <- which(data2 %in% data1)
-        }
-        if(same.length == TRUE & ! all(is.null(same.compartment.pos1), is.null(same.compartment.pos2))){
-            if(identical(same.compartment.pos1, same.compartment.pos2)){
-                identical.content <- TRUE
-            }else{
-                identical.content <- FALSE
-            }
-        }else{
-            identical.content <- FALSE
-        }
-    }
-    output <- list(same.length = same.length, length = length, same.names = same.names, name = name, any.id.name = any.id.name, same.names.pos1 = same.names.pos1, same.names.pos2 = same.names.pos2, any.id.compartment = any.id.compartment, same.compartment.pos1 = same.compartment.pos1, same.compartment.pos2 = same.compartment.pos2, identical.object = identical.object, identical.content = identical.content)
-    return(output)
+if( ! any(class(data2) %in% c("logical", "integer", "numeric", "character", "factor", "table"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A NON NULL VECTOR, FACTOR OR 1D TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(all(class(data2) %in% "table")){
+if(length(dim(data2)) > 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A 1D TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
 }
-
-
-######## fun_test() #### test combinations of argument values of a function and return errors (and graphs)
-
-
-# add traceback https://stackoverflow.com/questions/47414119/how-to-read-a-traceback-in-r
-
-fun_test <- function(
-    fun, 
-    arg, 
-    val, 
-    expect.error = NULL, 
-    parall = FALSE, 
-    thread.nb = NULL, 
-    print.count = 10, 
-    plot.fun = FALSE, 
-    export = FALSE, 
-    res.path = NULL, 
-    lib.path = NULL, 
-    cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
-){
-    # AIM
-    # test combinations of argument values of a function
-    # WARNINGS
-    # Limited to 43 arguments with at least 2 values each. The total number of arguments tested can be more if the additional arguments have a single value. The limit is due to nested "for" loops (https://stat.ethz.ch/pipermail/r-help/2008-March/157341.html), but it should not be a problem since the number of tests would be 2^43 > 8e12
-    # ARGUMENTS
-    # fun: character string indicating the name of the function tested (without brackets)
-    # arg: vector of character strings of arguments of fun. At least arguments that do not have default values must be present in this vector
-    # val: list with number of compartments equal to length of arg, each compartment containing values of the corresponding argument in arg. Each different value must be in a list or in a vector. For instance, argument 3 in arg is a logical argument (values accepted TRUE, FALSE, NA). Thus, compartment 3 of val can be either list(TRUE, FALSE, NA), or c(TRUE, FALSE, NA). NULL value alone must be written list(NULL)
-    # expect.error: list of exactly the same structure as val argument, but containing FALSE or TRUE, depending on whether error is expected (TRUE) or not (FALSE) for each corresponding value of val. A message is returned depending on discrepancies between the expected and observed errors. BEWARE: not always possible to write the expected errors for all the combination of argument values. Ignored if NULL
-    # parall: logical. Force parallelization ?
-    # thread.nb: numeric value indicating the number of threads to use if ever parallelization is required. If NULL, all the available threads will be used. Ignored if parall is FALSE
-    # print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
-    # plot.fun: logical. Plot the plotting function tested for each test?
-    # export: logical. Export the results into a .RData file and into a .txt file? If FALSE, return a list into the console (see below). BEWARE: will be automatically set to TRUE if parall is TRUE. This means that when using parallelization, the results are systematically exported, not returned into the console
-    # res.path: character string indicating the absolute pathway of folder where the txt results and pdfs, containing all the plots, will be saved. Several txt and pdf, one per thread, if parallelization. Ignored if export is FALSE. Must be specified if parall is TRUE or if export is TRUE
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # cute.path: character string indicating the absolute path of the cute.R file. Will be remove when cute will be a package. Ignored if parall is FALSE
-    # REQUIRED PACKAGES
-    # lubridate
-    # parallel if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
-    # pdftools if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
-    # If the tested function is in a package, this package must be imported first (no parallelization) or must be in the classical R package folder indicated by the lib.path argument (parallelization)
-    # RETURN
-    # if export is FALSE a list containing:
-    # $fun: the tested function
-    # $instruction: the initial instruction
-    # $sys.info: system and packages info
-    # $data: a data frame of all the combination tested, containing the following columns:
-    # the different values tested, named by arguments
-    # $kind: a vector of character strings indicating the kind of test result: either "ERROR", or "WARNING", or "OK"
-    # $problem: a logical vector indicating if error or not
-    # $expected.error: optional logical vector indicating the expected error specified in the expect.error argument
-    # $message: either NULL if $kind is always "OK", or the messages
-    # if export is TRUE 1) the same list object into a .RData file, 2) also the $data data frame into a .txt file, and 3) if expect.error is non NULL and if any discrepancy, the $data data frame into a .txt file but containing only the rows with discrepancies between expected and observed errors
-    # one or several pdf if a plotting function is tested and if the plot.fun argument is TRUE
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_get_message()
-    # fun_pack()
-    # EXAMPLES
-    # fun_test(fun = "unique", arg = c("x", "incomparables"), val = list(x = list(1:10, c(1,1,2,8), NA), incomparable = c(TRUE, FALSE, NA)))
-    # fun_test(fun = "fun_round", arg = c("data", "dec.nb", "after.lead.zero"), val = list(L1 = list(c(1, 1.0002256, 1.23568), "a", NA), L2 = list(2, c(1,3), NA), L3 = c(TRUE, FALSE, NA)))
-    # fun_test(fun = "plot", arg = c("x", "y"), val = list(x = list(1:10, 12:13, NA, (1:10)^2), y = list(1:10, NA, NA)),  expect.error = list(x = list(FALSE, TRUE, TRUE, FALSE), y = list(FALSE, TRUE, TRUE)), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = NULL)
-    # fun_test(fun = "plot", arg = c("x", "y"), val = list(x = list(1:10, 12:13, NA, (1:10)^2), y = list(1:10, NA, NA)), parall = FALSE, thread.nb = 4, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\")
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_test(fun = "fun_gg_boxplot", arg = c("data1", "y", "categ"), val = list(L1 = list(L1 = obs1), L2 = list(L1 = "Time"), L3 = list(L1 = "Group1")))
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_test(fun = "fun_gg_boxplot", arg = c("data1", "y", "categ"), val = list(L1 = list(obs1), L2 = "Time", L3 = "Group1"), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\")
-    # library(ggplot2) ; fun_test(fun = "geom_histogram", arg = c("data", "mapping"), val = list(x = list(data.frame(X = "a", stringsAsFactors = TRUE)), y = list(ggplot2::aes(x = X))), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\") # BEWARE: ggplot2::geom_histogram does not work
-    # DEBUGGING
-    # fun = "unique" ; arg = "x" ; val = list(x = list(1:10, c(1,1,2,8), NA)) ; expect.error = list(x = list(FALSE, FALSE, TRUE)) ; parall = FALSE ; thread.nb = NULL ; plot.fun = FALSE ; export = FALSE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 1 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
-    # fun = "unique" ; arg = c("x", "incomparables") ; val = list(x = list(1:10, c(1,1,2,8), NA), incomparable = c(TRUE, FALSE, NA)) ; expect.error = NULL ; parall = FALSE ; thread.nb = 2 ; plot.fun = FALSE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 10 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
-    # fun = "plot" ; arg = c("x", "y") ; val = list(x = list(1:10, 12:13, NA), y = list(1:10, NA, NA)) ; expect.error = list(x = list(FALSE, FALSE, TRUE, FALSE), y = list(FALSE, TRUE, TRUE)) ; print.count = 10 ; parall = FALSE ; thread.nb = NULL ; plot.fun = TRUE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL # for function debugging
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun = "fun_gg_boxplot" ; arg = c("data1", "y", "categ") ; val = list(L1 = list(L1 = obs1), L2 = list(L1 = "Time"), L3 = list(L1 = "Group1")) ; expect.error = NULL ; print.count = 10 ; parall = FALSE ; thread.nb = NULL ; plot.fun = TRUE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL # for function debugging
-    # fun = "unique" ; arg = "x" ; val = list(list(1:3, mean)) ; expect.error = list(TRUE, TRUE) ; parall = FALSE ; thread.nb = NULL ; plot.fun = FALSE ; export = FALSE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 1 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check", 
-        "fun_get_message", 
-        "fun_pack"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # arg with no default values
-    mandat.args <- c(
-        "fun", 
-        "arg", 
-        "val"
-    )
-    tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), "))")))
-    print(tempo)
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = fun, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = arg, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = val, class = "list", fun.name = function.name) ; eval(ee)
-    if( ! is.null(expect.error)){
-        tempo <- fun_check(data = expect.error, class = "list", fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = parall, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(parall == TRUE){
-        if( ! is.null(thread.nb)){
-            tempo <- fun_check(data = thread.nb, typeof = "integer", double.as.integer.allowed = TRUE, neg.values = FALSE, length = 1, fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE & thread.nb < 1){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": thread.nb PARAMETER MUST EQUAL OR GREATER THAN 1: ", thread.nb)
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = plot.fun, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = export, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(res.path)){
-        tempo <- fun_check(data = res.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = cute.path, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # new environment
-    env.name <- paste0("env", as.numeric(Sys.time()))
-    if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
-        tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        assign(env.name, new.env())
-        assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
-    }
-    # end new environment
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "fun", 
-        "arg", 
-        "val", 
-        # "expect.erro", # because can be NULL
-        "parall", 
-        # "thread.nb", # because can be NULL
-        "print.count", 
-        "plot.fun", 
-        "export", 
-        # "res.path", # because can be NULL
-        # "lib.path", # because can be NULL
-        "cute.path"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    # end warning initiation
-    # other checkings
-    if(grepl(x = fun, pattern = "()$")){ # remove ()
-        fun <- sub(x = fun, pattern = "()$", replacement = "")
-    }
-    if( ! exists(fun)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CHARACTER STRING IN fun ARGUMENT DOES NOT EXIST IN THE R WORKING ENVIRONMENT: ", paste(fun, collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }else if( ! all(base::class(get(fun)) == "function")){ # here no env = sys.nframe(), inherit = FALSE for get() because fun is a function in the classical scope
-        tempo.cat <- paste0("ERROR IN ", function.name, ": fun ARGUMENT IS NOT CLASS \"function\" BUT: ", paste(base::class(get(fun)), collapse = "\n"), "\nCHECK IF ANY CREATED OBJECT WOULD HAVE THE NAME OF THE TESTED FUNCTION")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(tempo$problem == FALSE & base::length(arg) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": arg ARGUMENT CANNOT BE LENGTH 0")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    for(i2 in 1:base::length(val)){
-        tempo1 <- fun_check(data = val[[i2]], class = "vector", na.contain = TRUE, fun.name = function.name)
-        tempo2 <- fun_check(data = val[[i2]], class = "list", na.contain = TRUE, fun.name = function.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": COMPARTMENT ", i2, " OF val ARGUMENT MUST BE A VECTOR OR A LIST")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }else if(tempo1$problem == FALSE){ # vector split into list compartments
-            val[[i2]] <- split(x = val[[i2]], f = 1:base::length(val[[i2]]))
-        }
-    }
-    if(base::length(arg) != base::length(val)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF arg ARGUMENT MUST BE IDENTICAL TO LENGTH OF val ARGUMENT:\nHERE IT IS: ", base::length(arg), " VERSUS ", base::length(val))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    args <- names(formals(get(fun))) # here no env = sys.nframe(), inherit = FALSE for get() because fun is a function in the classical scope
-    if( ! all(arg %in% args)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": SOME OF THE STRINGS IN arg ARE NOT ARGUMENTS OF fun\nfun ARGUMENTS: ", paste(args, collapse = " "),"\nPROBLEMATIC STRINGS IN arg: ", paste(arg[ ! arg %in% args], collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(sum(sapply(val, FUN = length) > 1) > 43){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CANNOT TEST MORE THAN 43 ARGUMENTS IF THEY ALL HAVE AT LEAST 2 VALUES EACH\nHERE THE NUMBER IS: ", sum(sapply(val, FUN = length) > 1))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if( ! is.null(expect.error)){
-        if(base::length(val) != base::length(expect.error)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF val ARGUMENT MUST BE IDENTICAL TO LENGTH OF expect.error ARGUMENT:\nHERE IT IS: ", base::length(val), " VERSUS ", base::length(expect.error))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-        for(i3 in 1:base::length(expect.error)){
-            tempo1 <- fun_check(data = expect.error[[i3]], class = "vector",  mode = "logical", fun.name = function.name)
-            tempo2 <- fun_check(data =  expect.error[[i3]], class = "list", fun.name = function.name)
-            if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": COMPARTMENT ", i3, " OF expect.error ARGUMENT MUST BE TRUE OR FALSE")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-            }else if(tempo1$problem == FALSE){ # vector split into list compartments
-                expect.error[[i3]] <- split(x = expect.error[[i3]], f = 1:base::length(expect.error[[i3]]))
-            }
-        }
-    }
-    if( ! is.null(res.path)){
-        if( ! all(dir.exists(res.path))){ # separation to avoid the problem of tempo$problem == FALSE and res.path == NA
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE res.path ARGUMENT DOES NOT EXISTS:\n", paste(res.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-    }
-    if(parall == TRUE & is.null(res.path)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": res.path ARGUMENT MUST BE SPECIFIED IF parall ARGUMENT IS TRUE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(is.null(res.path) & export == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": res.path ARGUMENT MUST BE SPECIFIED IF export ARGUMENT TRUE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(parall == TRUE & export == FALSE){
-        export <- TRUE
-        tempo.cat <- paste0("WARNING FROM ", function.name, ": export ARGUMENT CONVERTED TO TRUE BECAUSE thread.nb ARGUMENT IS NOT NULL")
-        warning(paste0("\n", tempo.cat, "\n"), call. = FALSE)
-    }
-    if( ! is.null(lib.path)){
-        if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-    }
-    if(parall == TRUE){
-        if(grepl(x = cute.path, pattern = "^http")){
-            tempo.error1 <- any(grepl(x = fun_get_message(data = "source(cute.path)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE)), pattern = "^[Ee]rror"))
-            tempo.error2 <- FALSE
-        }else{
-            tempo.error1 <- FALSE
-            tempo.error2 <- ! file.exists(cute.path)
-        }
-        if(tempo.error1 | tempo.error2){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(grepl(x = cute.path, pattern = "^http"), "URL", "FILE"), " PATH INDICATED IN THE cute.path PARAMETER DOES NOT EXISTS:\n", cute.path)
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-    }
-    # end other checkings
-    # reserved word checking
-    # end reserved word checking
-    # end second round of checking and data preparation
-    # package checking
-    fun_pack(req.package = c("lubridate"), lib.path = lib.path)
-    if(parall == TRUE){
-        fun_pack(req.package = c("parallel", "pdftools"), lib.path = lib.path)
-    }
-    # end package checking
-    # declaration of special plot functions
-    sp.plot.fun <- c("fun_gg_scatter", "fun_gg_bar", "fun_gg_boxplot")
-    # end declaration of special plot functions
-    # main code
-    ini.warning.length <- base::options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    cat("\nfun_test JOB IGNITION\n")
-    ini.date <- Sys.time()
-    ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
-    if(export == TRUE){
-        res.path <- paste0(res.path, "/fun_test_res_", trunc(ini.time))
-        if(dir.exists(res.path)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": FOLDER ALREADY EXISTS\n", res.path, "\nPLEASE RERUN ONCE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            dir.create(res.path)
-        }
-    }
-    total.comp.nb <- prod(sapply(val, FUN = "length"))
-    cat(paste0("\nTHE TOTAL NUMBER OF TESTS IS: ", total.comp.nb, "\n"))
-    # creation of the txt instruction that includes several loops
-    loop.string <- NULL
-    end.loop.string <- NULL
-    fun.args <- NULL
-    fun.args2 <- NULL
-    error.values <- NULL
-    arg.values <- "list("
-    for(i1 in 1:base::length(arg)){
-        if(parall == FALSE){
-            if(base::length(val[[i1]]) > 1){ # loop only if more than one value in base::length(val[[i1]])
-                loop.string <- paste0(loop.string, "for(i", i1, " in 1:", base::length(val[[i1]]), "){")
-                end.loop.string <- paste0(end.loop.string, "}")
-            }
-        }else{
-            loop.string <- "for(i in x){"
-            end.loop.string <- "}"
-        }
-        fun.args <- paste0(
-            fun.args, 
-            ifelse(i1 == 1L, "", ", "), 
-            arg[i1], 
-            " = val[[", 
-            i1, 
-            "]][[", 
-            if(parall == FALSE){
-                if(base::length(val[[i1]]) > 1){
-                    paste0("i", i1)
-                }else{
-                    "1" # a unique element in val[[i1]]
-                }
-            }else{
-                paste0("i.list[[", i1, "]][i]")
-            }, 
-            "]]"
-        )
-        fun.args2 <- paste0(
-            fun.args2, 
-            ifelse(i1 == 1L, "", ", "), 
-            arg[i1], 
-            " = val[[", 
-            i1, 
-            "]][[', ", 
-            if(parall == FALSE){
-                if(base::length(val[[i1]]) > 1){
-                    paste0("i", i1)
-                }else{
-                    "1" # a unique element in val[[i1]]
-                }
-            }else{
-                paste0("i.list[[", i1, "]][i]")
-            }, 
-            ", ']]"
-        )
-        arg.values <- paste0(
-            arg.values, 
-            "val[[", i1, "]][[", 
-            if(parall == FALSE){
-                if(base::length(val[[i1]]) > 1){
-                    paste0("i", i1)
-                }else{
-                    "1" # a unique element in val[[i1]]
-                }
-            }else{
-                paste0("i.list[[", i1, "]][i]")
-            }, 
-            "]]", 
-            ifelse(i1 == base::length(arg), "", ", ")
-        )
-        error.values <- paste0(
-            error.values, 
-            ifelse(i1 == 1L, "", " | "), 
-            "expect.error[[", i1, "]][[", 
-            if(parall == FALSE){
-                if(base::length(expect.error[[i1]]) > 1){
-                    paste0("i", i1)
-                }else{
-                    "1" # a unique element in expect.error[[i1]]
-                }
-            }else{
-                paste0("i.list[[", i1, "]][i]")
-            }, 
-            "]]"
-        )
-    }
-    arg.values <- paste0(arg.values, ")")
-    fun.test <- paste0(fun, "(", fun.args, ")")
-    fun.test2 <- paste0("paste0('", fun, "(", fun.args2, ")')")
-    # plot title for special plot functions
-    if(plot.fun == TRUE){
-        plot.kind <- "classic"
-        if(fun %in% sp.plot.fun){
-            plot.kind <- "special"
-            if(any(arg %in% "title")){ # this is for the special functions
-                tempo.match <- regmatches(x = fun.test, m = regexpr(text = fun.test, pattern = "title = .+[,)]"))
-                tempo.match <- substring(tempo.match , 1, nchar(tempo.match) - 1)
-                fun.test <- sub(x = fun.test, pattern = tempo.match, replacement = paste0(tempo.match, "\ntempo.title"))
-            }else{
-                fun.test <- sub(x = fun.test, pattern = ")$", replacement = ", title = tempo.title)")
-            }
-        }
-    }
-    # end plot title for special plot functions
-    kind <- character()
-    problem <- logical()
-    expected.error <- logical()
-    res <- character()
-    count <- 0
-    print.count.loop <- 0
-    plot.count <- 0
-    if(base::length(arg) == 1L){
-        data <- data.frame()
-    }else{ # base::length(arg) == 0L already tested above
-        data <- data.frame(t(vector("character", base::length(arg))), stringsAsFactors = FALSE)[-1, ] # -1 to remove the single row created and to have an empty data frame with base::length(arg) columns
-    }
-    code <- paste(
-        loop.string, '
-count <- count + 1
-print.count.loop <- print.count.loop + 1
-arg.values.print <- eval(parse(text = arg.values)) # recover the list of the i1 compartment
-for(j3 in 1:base::length(arg.values.print)){ # WARNING: do not use i1, i2 etc., here because already in loop.string
-tempo.capt <- capture.output(tempo.error <- fun_get_message(data =  paste0("paste(arg.values.print[[", j3, "]])"), kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))) # collapsing arg.values sometimes does not work (with function for instance)
-if( ! is.null(tempo.error)){
-arg.values.print[[j3]] <- paste0("SPECIAL VALUE OF CLASS ", base::class(arg.values.print[[j3]]), " AND TYPE ", base::typeof(arg.values.print[[j3]]))
 }
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
+# end argument checking
+# main code
+same.class <- FALSE
+class <- NULL
+same.length <- FALSE
+length <- NULL
+same.levels <- NULL # not FALSE to deal with no factors
+levels <- NULL
+any.id.levels <- FALSE
+same.levels.pos1 <- NULL
+same.levels.pos2 <- NULL
+same.levels.match1 <- NULL
+same.levels.match2 <- NULL
+common.levels <- NULL
+same.names <- NULL # not FALSE to deal with absence of name
+name <- NULL
+any.id.name <- FALSE
+same.names.pos1 <- NULL
+same.names.pos2 <- NULL
+same.names.match1 <- NULL
+same.names.match2 <- NULL
+common.names <- NULL
+any.id.element <- FALSE
+same.elements.pos1 <- NULL
+same.elements.pos2 <- NULL
+same.elements.match1 <- NULL
+same.elements.match2 <- NULL
+common.elements <- NULL
+same.order <- NULL
+order1 <- NULL
+order2 <- NULL
+identical.object <- FALSE
+identical.content <- FALSE
+if(identical(data1, data2)){
+same.class <- TRUE
+class <- class(data1)
+same.length <- TRUE
+length <- length(data1)
+if(any(class(data1) %in% "factor")){
+same.levels <- TRUE
+levels <- levels(data1)
+any.id.levels <- TRUE
+same.levels.pos1 <- 1:length(levels(data1))
+same.levels.pos2 <- 1:length(levels(data2))
+same.levels.match1 <- 1:length(levels(data1))
+same.levels.match2 <- 1:length(levels(data2))
+common.levels <- levels(data1)
 }
-data <- rbind(data, as.character(sapply(arg.values.print, FUN = "paste", collapse = " ")), stringsAsFactors = FALSE) # each colum is a test
-tempo.capt <- capture.output(tempo.try.error <- fun_get_message(data = eval(parse(text = fun.test2)), kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))) # data argument needs a character string but eval(parse(text = fun.test2)) provides it (eval parse replace the i1, i2, etc., by the correct values, meaning that only val is required in the env.name environment)
-tempo.capt <- capture.output(tempo.try.warning <- fun_get_message(data = eval(parse(text = fun.test2)), kind = "warning", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE), print.no = TRUE)) # data argument needs a character string but eval(parse(text = fun.test2)) provides it (eval parse replace the i1, i2, etc., by the correct values, meaning that only val is required in the env.name environment)
-if( ! is.null(expect.error)){
-expected.error <- c(expected.error, eval(parse(text = error.values)))
+if( ! is.null(names(data1))){
+same.names <- TRUE
+name <- names(data1)
+any.id.name <- TRUE
+same.names.pos1 <- 1:length(data1)
+same.names.pos2 <- 1:length(data2)
+same.names.match1 <- 1:length(data1)
+same.names.match2 <- 1:length(data2)
+common.names <- names(data1)
 }
-if( ! is.null(tempo.try.error)){
-kind <- c(kind, "ERROR")
-problem <- c(problem, TRUE)
-res <- c(res, tempo.try.error)
-}else{
-if( ! is.null(tempo.try.warning)){
-kind <- c(kind, "WARNING")
-problem <- c(problem, FALSE)
-res <- c(res, tempo.try.warning)
+any.id.element <- TRUE
+same.elements.pos1 <- 1:length(data1)
+same.elements.pos2 <- 1:length(data2)
+same.elements.match1 <- 1:length(data1)
+same.elements.match2 <- 1:length(data2)
+common.elements <- data1
+same.order <- TRUE
+order1 <- order(data1)
+order2 <- order(data2)
+identical.object <- TRUE
+identical.content <- TRUE
 }else{
-kind <- c(kind, "OK")
-problem <- c(problem, FALSE)
-res <- c(res, "")
+if(identical(class(data1), class(data2))){
+same.class <- TRUE
+class <- class(data1)
 }
-if(plot.fun == TRUE){
-invisible(dev.set(window.nb))
-plot.count <- plot.count + 1
-tempo.title <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), ifelse(parall == FALSE, count, x[count])))
-if(plot.kind == "classic"){
-eval(parse(text = fun.test))
-tempo <- fun_post_plot(corner.text = tempo.title)
-}else if(plot.kind == "special"){
-eval(parse(text = fun.test))
+if(identical(length(data1), length(data2))){
+same.length<- TRUE
+length <- length(data1)
+}
+if(any(class(data1) %in% "factor") & any(class(data2) %in% "factor")){
+if(identical(levels(data1), levels(data2))){
+same.levels <- TRUE
+levels <- levels(data1)
 }else{
-tempo.cat <- paste0("INTERNAL CODE ERROR 1 IN ", function.name, ": CODE HAS TO BE MODIFIED")
-stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+same.levels <- FALSE
 }
+if(any(levels(data1) %in% levels(data2))){
+any.id.levels <- TRUE
+same.levels.pos1 <- which(levels(data1) %in% levels(data2))
+same.levels.match1 <- match(levels(data1), levels(data2))
 }
+if(any(levels(data2) %in% levels(data1))){
+any.id.levels <- TRUE
+same.levels.pos2 <- which(levels(data2) %in% levels(data1))
+same.levels.match2 <- match(levels(data2), levels(data1))
 }
-if(print.count.loop == print.count){
-print.count.loop <- 0
-tempo.time <- as.numeric(Sys.time())
-tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-final.loop <- (tempo.time - ini.time) / count * ifelse(parall == FALSE, total.comp.nb, base::length(x)) # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
-final.exp <- as.POSIXct(final.loop, origin = ini.date)
-cat(paste0(ifelse(parall == FALSE, "\n", paste0("\nIN PROCESS ", process.id, " | ")), "LOOP ", format(count, big.mark=","), " / ", format(ifelse(parall == FALSE, total.comp.nb, base::length(x)), big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+if(any.id.levels == TRUE){
+common.levels <- unique(c(levels(data1)[same.levels.pos1], levels(data2)[same.levels.pos2]))
 }
-if(count == ifelse(parall == FALSE, total.comp.nb, base::length(x))){
-tempo.time <- as.numeric(Sys.time())
-tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-cat(paste0(ifelse(parall == FALSE, "\nLOOP PROCESS ENDED | ", paste0("\nPROCESS ", process.id, " ENDED | ")), "LOOP ", format(count, big.mark=","), " / ", format(ifelse(parall == FALSE, total.comp.nb, base::length(x)), big.mark=","), " | TIME SPENT: ", tempo.lapse, "\n\n"))
 }
-', 
-end.loop.string
-    )
-    # end creation of the txt instruction that includes several loops
-    if(parall == TRUE){
-        # list of i numbers that will be split
-        i.list <- vector("list", base::length(val)) # positions to split in parallel jobs
-        for(i2 in 1:base::length(arg)){
-            if(i2 == 1L){
-                tempo.divisor <- total.comp.nb / base::length(val[[i2]])
-                i.list[[i2]] <- rep(1:base::length(val[[i2]]), each = as.integer(tempo.divisor))
-                tempo.multi <- base::length(val[[i2]])
-            }else{
-                tempo.divisor <- tempo.divisor / base::length(val[[i2]])
-                i.list[[i2]] <- rep(rep(1:base::length(val[[i2]]), each = as.integer(tempo.divisor)), time = as.integer(tempo.multi))
-                tempo.multi <- tempo.multi * base::length(val[[i2]])
-            }
-        }
-        # end list of i numbers that will be split
-        tempo.cat <- paste0("PARALLELIZATION INITIATED AT: ", ini.date)
-        cat(paste0("\n", tempo.cat, "\n"))
-        tempo.thread.nb = parallel::detectCores(all.tests = FALSE, logical = TRUE) # detect the number of threads
-        if(tempo.thread.nb < thread.nb){
-            thread.nb <- tempo.thread.nb
-        }
-        tempo.cat <- paste0("NUMBER OF THREADS USED: ", thread.nb)
-        cat(paste0("\n    ", tempo.cat, "\n"))
-        Clust <- parallel::makeCluster(thread.nb, outfile = paste0(res.path, "/fun_test_parall_log.txt")) # outfile to print or cat during parallelization (only possible in a file, outfile = "" do not work on windows)
-        tempo.cat <- paste0("SPLIT OF TEST NUMBERS IN PARALLELISATION:")
-        cat(paste0("\n    ", tempo.cat, "\n"))
-        cluster.list <- parallel::clusterSplit(Clust, 1:total.comp.nb) # split according to the number of cluster
-        str(cluster.list) # using print(str()) add a NULL below the result
-        cat("\n")
-        paral.output.list <- parallel::clusterApply( # paral.output.list is a list made of thread.nb compartments, each made of n / thread.nb (mat theo column number) compartment. Each compartment receive the corresponding results of fun_permut(), i.e., data (permuted mat1.perm), warning message, cor (final correlation) and count (number of permutations)
-            cl = Clust,
-            x = cluster.list,
-            function.name = function.name, 
-            instruction = instruction, 
-            thread.nb = thread.nb, 
-            print.count = print.count, 
-            total.comp.nb = total.comp.nb, 
-            sp.plot.fun = sp.plot.fun,
-            i.list = i.list, 
-            fun.tested = fun,
-            arg.values = arg.values,
-            fun.test = fun.test,
-            fun.test2 = fun.test2,
-            kind = kind,
-            problem = problem,
-            res = res,
-            count = count,
-            plot.count = plot.count,
-            data = data,
-            code = code,
-            plot.fun = plot.fun, 
-            res.path = res.path, 
-            lib.path = lib.path, 
-            cute.path = cute.path, 
-            fun = function(
-                x, 
-                function.name, 
-                instruction, 
-                thread.nb, 
-                print.count, 
-                total.comp.nb, 
-                sp.plot.fun, 
-                i.list, 
-                fun.tested, 
-                arg.values, 
-                fun.test, 
-                fun.test2, 
-                kind, 
-                problem, 
-                res, 
-                count, 
-                plot.count, 
-                data, 
-                code, 
-                plot.fun, 
-                res.path, 
-                lib.path, 
-                cute.path
-            ){
-                # check again: very important because another R
-                process.id <- Sys.getpid()
-                cat(paste0("\nPROCESS ID ", process.id, " -> TESTS ", x[1], " TO ", x[base::length(x)], "\n"))
-                source(cute.path, local = .GlobalEnv)
-                fun_pack(req.package = "lubridate", lib.path = lib.path, load = TRUE) # load = TRUE to be sure that functions are present in the environment. And this prevent to use R.lib.path argument of fun_python_pack()
-                # end check again: very important because another R
-                # plot management
-                if(plot.fun == TRUE){
-                    pdf(file = paste0(res.path, "/plots_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".pdf", paste0("-", x[base::length(x)], ".pdf"))))
-                }else{
-                    pdf(file = NULL) # send plots into a NULL file, no pdf file created
-                }
-                window.nb <- dev.cur()
-                invisible(dev.set(window.nb))
-                # end plot management
-                # new environment
-                ini.date <- Sys.time()
-                ini.time <- as.numeric(ini.date) # time of process begin, converted into 
-                env.name <- paste0("env", ini.time)
-                if(exists(env.name, where = -1)){ # verify if still ok when fun_test() is inside a function
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else{
-                    assign(env.name, new.env())
-                    assign("val", val, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # var replaced by val
-                }
-                # end new environment
-                print.count.loop <- 0
-                suppressMessages(suppressWarnings(eval(parse(text = code))))
-                colnames(data) <- arg
-                if( ! is.null(expect.error)){
-                    data <- data.frame(data, kind = kind, problem = problem, expected.error = expected.error, message = res, stringsAsFactors = FALSE)
-                }else{
-                    data <- data.frame(data, kind = kind, problem = problem, message = res, stringsAsFactors = FALSE)
-                }
-                row.names(data) <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), x))
-                sys.info <- sessionInfo()
-                sys.info$loadedOnly <- sys.info$loadedOnly[order(names(sys.info$loadedOnly))] # sort the packages
-                invisible(dev.off(window.nb))
-                rm(env.name) # optional, because should disappear at the end of the function execution
-                # output
-                output <- list(fun = fun, instruction = instruction, sys.info = sys.info) # data = data finally removed from the output list, because everything combined in a RData file at the end
-                save(output, file = paste0(res.path, "/fun_test_", x[1], ifelse(base::length(x) == 1L, ".RData", paste0("-", x[base::length(x)], ".RData"))))
-                if(plot.fun == TRUE & plot.count == 0L){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN PROCESS ", process.id, ": NO PDF PLOT BECAUSE ONLY ERRORS REPORTED")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    file.remove(paste0(res.path, "/plots_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".pdf", paste0("-", x[base::length(x)], ".pdf"))))
-                }
-                table.out <- as.matrix(data)
-                # table.out[table.out == ""] <- " " # does not work # because otherwise read.table() converts "" into NA
-                table.out <- gsub(table.out, pattern = "\n", replacement = " ")
-                write.table(table.out, file = paste0(res.path, "/table_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".txt", paste0("-", x[base::length(x)], ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
-            }
-        )
-        parallel::stopCluster(Clust)
-        # files assembly
-        if(base::length(cluster.list) > 1){
-            for(i2 in 1:base::length(cluster.list)){
-                tempo.file <- paste0(res.path, "/table_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".txt", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".txt"))) # txt file
-                tempo <- read.table(file = tempo.file, header = TRUE, stringsAsFactors = FALSE, sep = "\t", row.names = 1, comment.char = "", colClasses = "character") #  row.names = 1 (1st column) because now read.table() adds a NA in the header if the header starts by a tabulation, comment.char = "" because colors with #, colClasses = "character" otherwise convert "" (from NULL) into NA
-                if(file.exists(paste0(res.path, "/plots_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".pdf", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".pdf"))))){
-                    tempo.pdf <- paste0(res.path, "/plots_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".pdf", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".pdf"))) # pdf file
-                }else{
-                    tempo.pdf <- NULL
-                }
-                tempo.rdata <- paste0(res.path, "/fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".RData", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".RData"))) # RData file
-                if(i2 == 1L){
-                    final.file <- tempo
-                    final.pdf <- tempo.pdf
-                    # new env for RData combining
-                    env.name <- paste0("env", ini.time)
-                    if(exists(env.name, where = -1)){ # verify if still ok when fun_test() is inside a function
-                        tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-                        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                        # end new env for RData combining
-                    }else{
-                        assign(env.name, new.env())
-                        load(tempo.rdata, envir = get(env.name))
-                        tempo.rdata1 <- tempo.rdata
-                        assign("final.output", get("output", envir = get(env.name)), envir = get(env.name))
-                    }
-                }else{
-                    final.file <- rbind(final.file, tempo, stringsAsFactors = TRUE)
-                    final.pdf <- c(final.pdf, tempo.pdf)
-                    load(tempo.rdata, envir = get(env.name))
-                    if( ! identical(get("final.output", envir = get(env.name))[c("R.version", "locale", "platform")], get("output", envir = get(env.name))[c("R.version", "locale", "platform")])){
-                        tempo.cat <- paste0("ERROR IN ", function.name, ": DIFFERENCE BETWEEN OUTPUTS WHILE THEY SHOULD BE IDENTICAL\nPLEASE CHECK\n", tempo.rdata1, "\n", tempo.rdata)
-                        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                    }else{
-                        # add the differences in RData $sysinfo into final.output
-                        tempo.base1 <- sort(get("final.output", envir = get(env.name))$sys.info$basePkgs)
-                        tempo.base2 <- sort(get("output", envir = get(env.name))$sys.info$basePkgs)
-                        tempo.other1 <- names(get("final.output", envir = get(env.name))$sys.info$otherPkgs)
-                        tempo.other2 <- names(get("output", envir = get(env.name))$sys.info$otherPkgs)
-                        tempo.loaded1 <- names(get("final.output", envir = get(env.name))$sys.info$loadedOnly)
-                        tempo.loaded2 <- names(get("output", envir = get(env.name))$sys.info$loadedOnly)
-                        assign("final.output", {
-                            x <- get("final.output", envir = get(env.name))
-                            y <- get("output", envir = get(env.name))
-                            x$sys.info$basePkgs <- sort(unique(tempo.base1, tempo.base2))
-                            if( ! all(tempo.other2 %in% tempo.other1)){
-                                x$sys.info$otherPkgs <- c(x$sys.info$otherPkgs, y$sys.info$otherPkgs[ ! (tempo.other2 %in% tempo.other1)])
-                                x$sys.info$otherPkgs <- x$sys.info$otherPkgs[order(names(x$sys.info$otherPkgs))]
-                            }
-                            if( ! all(tempo.loaded2 %in% tempo.loaded1)){
-                                x$sys.info$loadedOnly <- c(x$sys.info$loadedOnly, y$sys.info$loadedOnly[ ! (tempo.loaded2 %in% tempo.loaded1)])
-                                x$sys.info$loadedOnly <- x$sys.info$loadedOnly[order(names(x$sys.info$loadedOnly))]
-                            }
-                            x
-                        }, envir = get(env.name))
-                        # add the differences in RData $sysinfo into final.output
-                    }
-                }
-                file.remove(c(tempo.file, tempo.rdata))
-            }
-            # combine pdf and save
-            if( ! is.null(final.pdf)){
-                pdftools::pdf_combine(
-                    input = final.pdf,
-                    output = paste0(res.path, "/plots_from_fun_test_1-", total.comp.nb, ".pdf")
-                )
-                file.remove(final.pdf)
-            }
-            # end combine pdf and save
-            # save RData
-            assign("output", c(get("final.output", envir = get(env.name)), data = list(final.file)), envir = get(env.name))
-            save(output, file = paste0(res.path, "/fun_test__1-", total.comp.nb, ".RData"), envir = get(env.name))
-            rm(env.name) # optional, because should disappear at the end of the function execution
-            # end save RData
-            # save txt
-            write.table(final.file, file = paste0(res.path, "/table_from_fun_test_1-", total.comp.nb, ".txt"), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
-            # end save txt
-            if( ! is.null(expect.error)){
-                final.file <- final.file[ ! final.file$problem == final.file$expected.error, ]
-                if(nrow(final.file) == 0L){
-                    cat(paste0("NO DISCREPANCY BETWEEN EXPECTED AND OBSERVED ERRORS\n\n"))
-                }else{
-                    cat(paste0("DISCREPANCIES BETWEEN EXPECTED AND OBSERVED ERRORS (SEE THE discrepancy_table_from_fun_test_1-", total.comp.nb, ".txt FILE)\n\n"))
-                    write.table(final.file, file = paste0(res.path, "/discrepancy_table_from_fun_test_1-", total.comp.nb, ".txt"), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
-                }
-            }
-        }
-        # end files assembly
-    }else{
-        # plot management
-        if(plot.fun == TRUE){
-            pdf(file = paste0(res.path, "/plots_from_fun_test_1", ifelse(total.comp.nb == 1L, ".pdf", paste0("-", total.comp.nb, ".pdf"))))
-        }else{
-            pdf(file = NULL) # send plots into a NULL file, no pdf file created
-        }
-        window.nb <- dev.cur()
-        invisible(dev.set(window.nb))
-        # end plot management
-        # new environment
-        env.name <- paste0("env", ini.time)
-        if(exists(env.name, where = -1)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            assign(env.name, new.env())
-            assign("val", val, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # var replaced by val
-        }
-        # end new environment
-        suppressMessages(suppressWarnings(eval(parse(text = code))))
-        colnames(data) <- arg
-        expect.data <- data.frame()
-        if( ! is.null(expect.error)){
-            data <- data.frame(data, kind = kind, problem = problem, expected.error = expected.error, message = res, stringsAsFactors = FALSE)
-        }else{
-            data <- data.frame(data, kind = kind, problem = problem, message = res, stringsAsFactors = FALSE)
-        }
-        row.names(data) <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), 1:total.comp.nb))
-        sys.info <- sessionInfo()
-        sys.info$loadedOnly <- sys.info$loadedOnly[order(names(sys.info$loadedOnly))] # sort the packages
-        invisible(dev.off(window.nb))
-        rm(env.name) # optional, because should disappear at the end of the function execution
-        # output
-        output <- list(fun = fun, instruction = instruction, sys.info = sys.info, data = data)
-        if(plot.fun == TRUE & plot.count == 0L){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NO PDF PLOT BECAUSE ONLY ERRORS REPORTED")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            file.remove(paste0(res.path, "/plots_from_fun_test_1", ifelse(total.comp.nb == 1L, ".pdf", paste0("-", total.comp.nb, ".pdf"))))
-        }
-        if( ! is.null(expect.error)){
-            expect.data <- output$data[ ! output$data$problem == output$data$expected.error, ]
-            if(nrow(expect.data) == 0L){
-                cat(paste0("NO DISCREPANCY BETWEEN EXPECTED AND OBSERVED ERRORS\n\n"))
-            }else{
-                cat(paste0("DISCREPANCIES BETWEEN EXPECTED AND OBSERVED ERRORS (SEE THE ", if(export == TRUE){paste0("discrepancy_table_from_fun_test_1", ifelse(total.comp.nb == 1L, "", paste0("-", total.comp.nb)), ".txt FILE")}else{"$data RESULT"}, ")\n\n"))
-                if(export == TRUE){
-                    expect.data <- as.matrix(expect.data)
-                    expect.data <- gsub(expect.data, pattern = "\n", replacement = "  ")
-                    write.table(expect.data, file = paste0(res.path, "/discrepancy_table_from_fun_test_1", ifelse(total.comp.nb == 1L, ".txt", paste0("-", total.comp.nb, ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
-                }
-            }
-        }
-        if( ! is.null(warn)){
-            base::options(warning.length = 8170)
-            on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-        }
-        on.exit(exp = base::options(warning.length = ini.warning.length), add = TRUE)
-        if(export == TRUE){
-            save(output, file = paste0(res.path, "/fun_test_1", ifelse(total.comp.nb == 1L, ".RData", paste0("-", total.comp.nb, ".RData"))))
-            table.out <- as.matrix(output$data)
-            table.out <- gsub(table.out, pattern = "\n", replacement = "  ")
-            write.table(table.out, file = paste0(res.path, "/table_from_fun_test_1", ifelse(total.comp.nb == 1L, ".txt", paste0("-", total.comp.nb, ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
-        }else{
-            return(output)
-        }
-    }
-    # after return() ?
-    end.date <- Sys.time()
-    end.time <- as.numeric(end.date)
-    total.lapse <- round(lubridate::seconds_to_period(end.time - ini.time))
-    cat(paste0("fun_test JOB END\n\nTIME: ", end.date, "\n\nTOTAL TIME LAPSE: ", total.lapse, "\n\n\n"))
+if(any(class(data1) %in% "factor")){ # to compare content
+data1 <- as.character(data1)
 }
-
-
-################ Object modification
-
-
-######## fun_name_change() #### check a vector of character strings and modify any string if present in another vector
-
-
-fun_name_change <- function(data1, data2, added.string = "_modif"){
-    # AIM
-    # this function allow to check if a vector of character strings, like column names of a data frame, has elements present in another vector (vector of reserved words or column names of another data frame before merging)
-    # ARGUMENTS
-    # data1: vector of character strings to check and modify
-    # data2: reference vector of character strings
-    # added.string: string added at the end of the modified string in data1 if present in data2
-    # RETURN
-    # a list containing
-    # $data: the modified data1 (in the same order as in the initial data1)
-    # $ini: the initial elements before modification. NULL if no modification
-    # $post: the modified elements in the same order as in ini. NULL if no modification
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # obs1 <- c("A", "B", "C", "D") ; obs2 <- c("A", "C") ; fun_name_change(obs1, obs2)
-    # obs1 <- c("A", "B", "C", "C_modif1", "D") ; obs2 <- c("A", "A_modif1", "C") ; fun_name_change(obs1, obs2) # the function checks that the new names are neither in obs1 nor in obs2 (increment the number after the added string)
-    # DEBUGGING
-    # data1 = c("A", "B", "C", "D") ; data2 <- c("A", "C") ; added.string = "_modif" # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data1, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = data2, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = added.string, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    ini <- NULL
-    post <- NULL
-    if(any(data1 %in% data2)){
-        tempo.names <- data1[data1 %in% data2]
-        ini <- NULL
-        post <- NULL
-        for(i2 in 1:length(tempo.names)){
-            count <- 0
-            tempo <- tempo.names[i2]
-            while(any(tempo %in% data2) | any(tempo %in% data1)){
-                count <- count + 1
-                tempo <- paste0(tempo.names[i2], "_modif", count)
-            }
-            data1[data1 %in% tempo.names[i2]] <- paste0(tempo.names[i2], "_modif", count)
-            if(count != 0){
-                ini <- c(ini, tempo.names[i2])
-                post <- c(post, paste0(tempo.names[i2], "_modif", count))
-            }
-        }
-        data <- data1
-    }else{
-        data <- data1
-    }
-    output <- list(data = data, ini = ini, post = post)
-    return(output)
+if(any(class(data2) %in% "factor")){ # to compare content
+data2 <- as.character(data2)
 }
-
-
-######## fun_df_remod() #### remodeling a data frame to have column name as a qualitative values and vice-versa
-
-
-fun_df_remod <- function(
-    data, 
-    quanti.col.name = "quanti", 
-    quali.col.name = "quali"
-){
-    # AIM
-    # if the data frame is made of n numeric columns, a new data frame is created, with the 1st column gathering all the numeric values, and the 2nd column being the name of the columns of the initial data frame. If row names were present in the initial data frame, then a new ini_rowname column is added with the names of the rows
-    
-    
-    # If the data frame is made of one numeric column and one character or factor column, a new data frame is created, with the new columns corresponding to the split numeric values (according to the character column). NA are added a the end of each column to have the same number of rows. BEWARE: in such data frame, rows are not individuals. This means that in the example below, values 10 and 20 are associated on the same row but that means nothing in term of association
-    
-    
-    
-    # ARGUMENTS
-    # data: data frame to convert
-    # quanti.col.name: optional name for the quanti column of the new data frame
-    # quali.col.name: optional name for the quali column of the new data frame
-    # RETURN
-    # the modified data frame
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # obs <- data.frame(col1 = (1:4)*10, col2 = c("A", "B", "A", "A"), stringsAsFactors = TRUE) ; obs ; fun_df_remod(obs)
-    # obs <- data.frame(col1 = (1:4)*10, col2 = 5:8, stringsAsFactors = TRUE) ; obs ; fun_df_remod(obs, quanti.col.name = "quanti", quali.col.name = "quali")
-    # obs <- data.frame(col1 = (1:4)*10, col2 = 5:8, stringsAsFactors = TRUE) ; rownames(obs) <- paste0("row", 1:4) ; obs ; fun_df_remod(obs, quanti.col.name = "quanti", quali.col.name = "quali")
-    # DEBUGGING
-    # data = data.frame(a = 1:3, b = 4:6, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
-    # data = data.frame(a = 1:3, b = 4:6, c = 11:13, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
-    # data = data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
-    # data = data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = TRUE) ; quanti.col.name = "TEST" ; quali.col.name = "quali" # for function debugging
-    # data = data.frame(b = letters[1:3], a = 1:3, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
-    # data = data.frame(b = c("e", "e", "h"), a = 1:3, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking without fun_check()
-    if( ! any(class(data) %in% "data.frame")){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data ARGUMENT MUST BE A DATA FRAME")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking without fun_check()
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = quanti.col.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = quali.col.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    tempo.factor <- unlist(lapply(data, class))
-    for(i in 1:length(tempo.factor)){ # convert factor columns as character
-        if(all(tempo.factor[i] == "factor")){
-            data[, i] <- as.character(data[, i])
-        }
-    }
-    tempo.factor <- unlist(lapply(data, mode))
-    if(length(data) == 2L){
-        if( ! ((base::mode(data[, 1]) == "character" & base::mode(data[, 2]) == "numeric") | base::mode(data[, 2]) == "character" & base::mode(data[, 1]) == "numeric" | base::mode(data[, 2]) == "numeric" & base::mode(data[, 1]) == "numeric") ){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": IF data ARGUMENT IS A DATA FRAME MADE OF 2 COLUMNS, EITHER A COLUMN MUST BE NUMERIC AND THE OTHER CHARACTER, OR THE TWO COLUMNS MUST BE NUMERIC")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if((base::mode(data[, 1]) == "character" | base::mode(data[, 2]) == "character") & (quanti.col.name != "quanti" | quali.col.name != "quali")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": IMPROPER quanti.col.name OR quali.col.name RESETTINGS. THESE ARGUMENTS ARE RESERVED FOR DATA FRAMES MADE OF n NUMERIC COLUMNS ONLY")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else{
-        if( ! all(tempo.factor %in% "numeric")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": IF data ARGUMENT IS A DATA FRAME MADE OF ONE COLUMN, OR MORE THAN 2 COLUMNS, THESE COLUMNS MUST BE NUMERIC")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(( ! any(tempo.factor %in% "character")) & is.null(names(data))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": NUMERIC DATA FRAME in the data ARGUMENT MUST HAVE COLUMN NAMES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(all(tempo.factor %in% "numeric")){ # transfo 1
-        quanti <- NULL
-        for(i in 1:length(data)){
-            quanti <-c(quanti, data[, i])
-        }
-        quali <- rep(names(data), each = nrow(data))
-        output.data <- data.frame(quanti, quali, stringsAsFactors = TRUE, check.names = FALSE)
-        names(output.data) <- c(quanti.col.name, quali.col.name)
-        # add the ini_rowname column
-        ini.rownames <- rownames(data)
-        tempo.data <- data
-        rownames(tempo.data) <- NULL
-        null.rownames <- (tempo.data)
-        if( ! identical(ini.rownames, null.rownames)){
-            ini_rowname <- rep(ini.rownames, times = ncol(data))
-            output.data <- cbind(output.data, ini_rowname, stringsAsFactors = TRUE)
-        }
-    }else{ # transfo 2
-        if(class(data[, 1]) == "character"){
-            data <- cbind(data[2], data[1], stringsAsFactors = TRUE)
-        }
-        nc.max <- max(table(data[, 2])) # effectif maximum des classes
-        nb.na <- nc.max - table(data[,2]) # nombre de NA à ajouter pour réaliser la data frame
-        tempo<-split(data[, 1], data[, 2])
-        for(i in 1:length(tempo)){tempo[[i]] <- append(tempo[[i]], rep(NA, nb.na[i]))} # des NA doivent être ajoutés lorsque les effectifs sont différents entre les classes. C'est uniquement pour que chaque colonne ait le même nombre de lignes
-        output.data<-data.frame(tempo, stringsAsFactors = TRUE, check.names = FALSE)
-    }
-    return(output.data)
+if( ! (is.null(names(data1)) & is.null(names(data2)))){
+if(identical(names(data1), names(data2))){
+same.names <- TRUE
+name <- names(data1)
+}else{
+same.names <- FALSE
 }
-
-
-
-
-######## fun_round() #### rounding number if decimal present
-
-
-fun_round <- function(data, dec.nb = 2, after.lead.zero = TRUE){
-    # AIM
-    # round a vector of values, if decimal, with the desired number of decimal digits after the decimal leading zeros
-    # WARNINGS
-    # Work well with numbers as character strings, but not always with numerical numbers because of the floating point
-    # Numeric values are really truncated from a part of their decimal digits, whatever options(digits) settings
-    # See ?.Machine or https://stackoverflow.com/questions/5173692/how-to-return-number-of-decimal-places-in-r, with the interexting formula: abs(x - round(x)) > .Machine$double.eps^0.5
-    # ARGUMENTS
-    # data: a vector of numbers (numeric or character mode)
-    # dec.nb: number of required decimal digits
-    # after.lead.zero: logical. If FALSE, rounding is performed for all the decimal numbers, whatever the leading zeros (e.g., 0.123 -> 0.12 and 0.00128 -> 0.00). If TRUE, dec.nb are taken after the leading zeros (e.g., 0.123 -> 0.12 and 0.00128 -> 0.0013)
-    # RETURN
-    # the modified vector
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, 10, 100.001, 333.0001254, 12312.1235), dec.nb = 2, after.lead.zero = FALSE), "\n\n") ; options(digits = ini.options)
-    # ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, 10, 100.001, 333.0001254, 12312.1235), dec.nb = 2, after.lead.zero = TRUE), "\n\n") ; options(digits = ini.options)
-    # ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, "10", "100.001", "333.0001254", "12312.1235"), dec.nb = 2, after.lead.zero = FALSE), "\n\n") ; options(digits = ini.options)
-    # ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, "10", "100.001", "333.0001254", "12312.1235"), dec.nb = 2, after.lead.zero = TRUE), "\n\n") ; options(digits = ini.options)
-    # DEBUGGING
-    # data = data = c(10, 100.001, 333.0001254, 12312.1235) ; dec.nb = 2 ; after.lead.zero = FALSE # # for function debugging
-    # data = data = c("10", "100.001", "333.0001254", "12312.1235") ; dec.nb = 2 ; after.lead.zero = TRUE # # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking without fun_check()
-    if( ! (all(typeof(data) == "character") | all(typeof(data) == "double") | all(typeof(data) == "integer"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A VECTOR OF NUMBERS (IN NUMERIC OR CHARACTER MODE)")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking without fun_check()
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data, class = "vector", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dec.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = after.lead.zero, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    tempo <- grepl(x = data, pattern = "\\.") # detection of decimal numbers
-    ini.mode <- base::mode(data)
-    data <- as.character(data) # to really truncate decimal digits
-    for(i in 1:length(data)){ # scan all the numbers of the vector
-        if(tempo[i] == TRUE){ # means decimal number
-            if(after.lead.zero == TRUE){
-                zero.pos <- unlist(gregexpr(text=data[i], pattern = 0)) # recover all the position of the zeros in the number. -1 if no zeros (do not record the leading and trailing zeros)
-            }else{
-                zero.pos <- -1 # -1 as if no zero
-            }
-            dot.pos <- unlist(gregexpr(text=data[i], pattern = "\\.")) # recover all the position of the zeros in the number
-            digit.pos <- unlist(gregexpr(text=data[i], pattern = "[[:digit:]]")) # recover all the position of the digits in the number
-            dec.pos <- digit.pos[digit.pos > dot.pos]
-            count <- 0
-            while((dot.pos + count + 1) %in% zero.pos & (dot.pos + count + 1) <= max(dec.pos) & (count + dec.nb) < length(dec.pos)){ # count the number of leading zeros in the decimal part
-                count <- count + 1
-            }
-            data[i] <- formatC(as.numeric(data[i]), digits = (count + dec.nb), format = "f")
-        }
-    }
-    if(ini.mode != "character"){
-        data <- as.numeric(data)
-    }
-    return(data)
+if(any(names(data1) %in% names(data2))){
+any.id.name <- TRUE
+same.names.pos1 <- which(names(data1) %in% names(data2))
+same.names.match1 <- match(names(data1), names(data2))
 }
-
-
-######## fun_mat_rotate() #### 90° clockwise matrix rotation
-
-
-fun_mat_rotate <- function(data){
-    # AIM
-    # 90° clockwise matrix rotation
-    # applied twice, the function provide the mirror matrix, according to vertical and horizontal symmetry
-    # ARGUMENTS
-    # data: matrix (matrix class)
-    # RETURN
-    # the modified matrix
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # obs <- matrix(1:10, ncol = 1) ; obs ; fun_mat_rotate(obs)
-    # obs <- matrix(LETTERS[1:10], ncol = 5) ; obs ; fun_mat_rotate(obs)
-    # DEBUGGING
-    # data = matrix(1:10, ncol = 1)
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data, class = "matrix", fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    for (i in 1:ncol(data)){data[,i] <- rev(data[,i])}
-    data <- t(data)
-    return(data)
+if(any(names(data2) %in% names(data1))){
+any.id.name <- TRUE
+same.names.pos2 <- which(names(data2) %in% names(data1))
+same.names.match2 <- match(names(data2), names(data1))
 }
-
-
-######## fun_mat_num2color() #### convert a numeric matrix into hexadecimal color matrix
-
-
-fun_mat_num2color <- function(
-    mat1, 
-    mat.hsv.h = TRUE, 
-    notch = 1, 
-    s = 1, 
-    v = 1, 
-    forced.color = NULL
-){
-    # AIM
-    # convert a matrix made of numbers into a hexadecimal matrix for rgb colorization
-    # ARGUMENTS:
-    # mat1: matrix 1 of non negative numerical values that has to be colored (matrix class). NA allowed
-    # mat.hsv.h: logical. Is mat1 the h of hsv colors ? (if TRUE, mat1 must be between zero and 1). If FALSE, mat1 must be made of positive integer values without 0
-    # notch: single value between 0 and 1 to shift the successive colors on the hsv circle by + notch
-    # s: s argument of hsv(). Must be between 0 and 1
-    # v: v argument of hsv(). Must be between 0 and 1
-    # forced.color: Must be NULL or hexadecimal color code or name given by colors(). The first minimal values of mat1 will be these colors. All the color of mat1 can be forced using this argument
-    # RETURN
-    # a list containing:
-    # $mat1.name: name of mat1
-    # $colored.mat: colors of mat1 in hexa
-    # $problem: logical. Is any colors of forced.color overlap the colors designed by the function. NULL if forced.color = NULL
-    # $text.problem: text when overlapping colors. NULL if forced.color = NULL or problem == FALSE
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # mat1 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; dimnames(mat1) <- list(LETTERS[1:4], letters[1:2]) ; fun_mat_num2color(mat1, mat.hsv.h = FALSE, notch = 1, s = 1, v = 1, forced.color = NULL)
-    # DEBUGGING
-    # mat1 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; dimnames(mat1) <- list(LETTERS[1:4], letters[1:2]); mat.hsv.h = FALSE ; notch = 1 ; s = 1 ; v = 1 ; forced.color = c(hsv(1,1,1), hsv(0,0,0)) # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = mat1, mode = "numeric", class = "matrix", na.contain = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = mat.hsv.h, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = notch, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = s, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = v, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # argument checking without fun_check()
-    if(mat.hsv.h == TRUE & fun_check(data = mat1, mode = "numeric", prop = TRUE)$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 ARGUMENT MUST BE A MATRIX OF PROPORTIONS SINCE THE mat.hsv.h ARGUMENT IS SET TO TRUE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(forced.color)){
-        tempo <- fun_check(data = forced.color, class = "character")
-        if(any(tempo$problem == TRUE)){
-            paste0("\n\n================\n\n", paste(tempo$text[tempo$problem], collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! all(forced.color %in% colors() | grepl(pattern = "^#", forced.color))){ # check that all strings of forced.color start by #
-            tempo.cat <- paste0("ERROR IN ", function.name, ": forced.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end argument checking without fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    problem <- NULL
-    text.problem <- NULL
-    mat1.name <- deparse(substitute(mat1))
-    # change the scale of the plotted matrix
-    if(mat.hsv.h == TRUE){
-        if(any(min(mat1, na.rm = TRUE) < 0 | max(mat1, na.rm = TRUE) > 1, na.rm = TRUE)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 MUST BE MADE OF VALUES BETWEEN 0 AND 1 BECAUSE mat.hsv.h ARGUMENT SET TO TRUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else{
-        if(any(mat1 - floor(mat1) > 0, na.rm = TRUE) | any(mat1 == 0L, na.rm = TRUE)){ # no need of isTRUE(all.equal()) because we do not require approx here but strictly 0, thus == is ok
-            tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 MUST BE MADE OF INTEGER VALUES WITHOUT 0 BECAUSE mat.hsv.h ARGUMENT SET TO FALSE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            mat1 <- mat1 / max(mat1, na.rm = TRUE)
-        }
-    }
-    if(notch != 1){
-        different.color <- unique(as.vector(mat1))
-        different.color <- different.color[ ! is.na(different.color)]
-        tempo.different.color <- different.color + c(0, cumsum(rep(notch, length(different.color) - 1)))
-        tempo.different.color <- tempo.different.color - floor(tempo.different.color)
-        if(any(duplicated(tempo.different.color) == TRUE)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DUPLICATED VALUES AFTER USING notch (", paste(tempo.different.color[duplicated(tempo.different.color)], collapse = " "), "). TRY ANOTHER notch VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(length(different.color) != length(tempo.different.color)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF different.color (", paste(different.color, collapse = " "), ") DIFFERENT FROM LENGTH OF tempo.different.color (", paste(tempo.different.color, collapse = " "), ")")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            for(i in 1:length(different.color)){
-                mat1[mat1 == different.color[i]] <- tempo.different.color[i] # no need of isTRUE(all.equal()) because different.color comes from mat1
-            }
-        }
-    }
-    if( ! is.null(forced.color)){
-        hexa.values.to.change <- hsv(unique(sort(mat1))[1:length(forced.color)], s, v)
-    }
-    mat1[ ! is.na(mat1)] <- hsv(mat1[ ! is.na(mat1)], s, v)
-    if( ! is.null(forced.color)){
-        if(any(forced.color %in% mat1, na.rm = TRUE)){
-            problem <- TRUE
-            text.problem <- paste0("THE FOLLOWING COLORS WHERE INTRODUCED USING forced.color BUT WHERE ALREADY PRESENT IN THE COLORED MATRIX :", paste(forced.color[forced.color %in% mat1], collapse = " "))
-        }else{
-            problem <- FALSE
-        }
-        for(i in 1:length(hexa.values.to.change)){
-            if( ! any(mat1 == hexa.values.to.change[i], na.rm = TRUE)){# no need of isTRUE(all.equal()) because character
-                tempo.cat <- paste0("ERROR IN ", function.name, ": THE ", hexa.values.to.change[i], " VALUE FROM hexa.values.to.change IS NOT REPRESENTED IN mat1 : ", paste(unique(as.vector(mat1)), collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                mat1[which(mat1 == hexa.values.to.change[i])] <- forced.color[i] # no need of isTRUE(all.equal()) because character
-            }
-        }
-    }
-    output <- list(mat1.name = mat1.name, colored.mat = mat1, problem = problem, text.problem = text.problem)
-    return(output)
+if(any.id.name == TRUE){
+common.names <- unique(c(names(data1)[same.names.pos1], names(data2)[same.names.pos2]))
 }
-
-
-######## fun_mat_op() #### assemble several matrices with operation
-
-
-fun_mat_op <- function(mat.list, kind.of.operation = "+"){
-    # AIM
-    # assemble several matrices of same dimensions by performing by case operation. For instance add the value of all the case 1 (row1 & column1) of the matrices and put it in the case 1 of a new matrix M, add the value of all the case 2 (row2 & column1) of the matrices and put it in the case 2 of a new matrix M, etc.
-    
-    # c: case
-    # i: row number
-    # j: column number
-    # k: matrix number
-    # z: number of matrices
-    # ARGUMENTS:
-    # mat.list: list of matrices
-    # kind.of.operation: either "+" (by case addition), "-" (by case subtraction) or "*" (by case multiplication)
-    # RETURN
-    # the assembled matrix, with row and/or column names only if all the matrices have identical row/column names
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_comp_2d()
-    # EXAMPLES
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "+")
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "*")
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], c(NA, NA))) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "-")
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(c("A1", "A2", "A3", "A4"), letters[1:2])) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat3 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2, mat3), kind.of.operation = "+")
-    # DEBUGGING
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; mat.list = list(mat1, mat2) ; kind.of.operation = "+" # for function debugging
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], c(NA, NA))) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat.list = list(mat1, mat2) ; kind.of.operation = "*" # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_comp_2d() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = mat.list, class = "list", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = kind.of.operation, options = c("+", "-", "*"), length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # argument checking without fun_check()
-    if(length(mat.list) < 2){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat.list ARGUMENT MUST BE A LIST CONTAINING AT LEAST 2 MATRICES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    for(i1 in 1:length(mat.list)){
-        tempo <- fun_check(data = mat.list[[i1]], class = "matrix", mode = "numeric", na.contain = TRUE)
-        if(tempo$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ELEMENT ", i1, " OF mat.list ARGUMENT MUST BE A NUMERIC MATRIX")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    ident.row.names <- TRUE
-    ident.col.names <- TRUE
-    for(i1 in 2:length(mat.list)){
-        tempo <- fun_comp_2d(data1 = mat.list[[1]], data2 = mat.list[[i1]])
-        if(tempo$same.dim == FALSE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX ", i1, " OF mat.list ARGUMENT MUST HAVE THE SAME DIMENSION (", paste(dim(mat.list[[i1]]), collapse = " "), ") THAN THE MATRIX 1 IN mat.list (", paste(dim(mat.list[[1]]), collapse = " "), ")")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! is.null(tempo$same.row.name)){
-            if(tempo$same.row.name != TRUE){ # != TRUE to deal with NA
-                ident.row.names <- FALSE
-            }
-        }
-        if( ! is.null(tempo$same.col.name)){
-            if(tempo$same.col.name != TRUE){ # != TRUE to deal with NA
-                ident.col.names <- FALSE
-            }
-        }
-    }
-    # end argument checking without fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    output <- mat.list[[1]]
-    for(i1 in 2:length(mat.list)){
-        output <- get(kind.of.operation)(output, mat.list[[i1]]) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-    }
-    dimnames(output) <- NULL
-    if(ident.row.names == TRUE){
-        rownames(output) <- rownames(mat.list[[1]])
-    }
-    if(ident.col.names == TRUE){
-        colnames(output) <- colnames(mat.list[[1]])
-    }
-    return(output)
 }
-
-
-######## fun_mat_inv() #### return the inverse of a square matrix
-
-
-fun_mat_inv <- function(mat){
-    # AIM
-    # return the inverse of a square matrix when solve() cannot
-    # ARGUMENTS:
-    # mat: a square numeric matrix without NULL, NA, Inf or single case (dimension 1, 1) of 0
-    # RETURN
-    # the inversed matrix
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # mat1 = matrix(c(1,1,1,2,1,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1) # use solve()
-    # mat1 = matrix(c(0,0,0,0,0,0,0,0,0), ncol = 3) ; fun_mat_inv(mat = mat1) # use the trick
-    # mat1 = matrix(c(1,1,1,2,Inf,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1)
-    # mat1 = matrix(c(1,1,1,2,NA,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1)
-    # mat1 = matrix(c(1,2), ncol = 1) ; fun_mat_inv(mat = mat1)
-    # mat1 = matrix(0, ncol = 1) ; fun_mat_inv(mat = mat1)
-    # mat1 = matrix(2, ncol = 1) ; fun_mat_inv(mat = mat1)
-    # DEBUGGING
-    # mat = matrix(c(1,1,1,2,1,5,9,8,9), ncol = 3) # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = mat, class = "matrix", mode = "numeric", fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # argument checking without fun_check()
-    if(ncol(mat) != nrow(mat)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A SQUARE MATRIX")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(mat %in% c(Inf, -Inf, NA))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A MATRIX WITHOUT Inf, -Inf OR NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(all(mat == 0L) & ncol(mat) == 1L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT CANNOT BE A SQUARE MATRIX MADE OF A SINGLE CASE OF 0")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking without fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if(any(grepl(x = try(solve(mat), silent = TRUE)[], pattern = "[Ee]rror"))){
-        tempo <- svd(mat)
-        val.critique <- which(tempo$d < 10^-8)
-        Diag.mod <- diag(1 / tempo$d)
-        for(i in val.critique){
-            Diag.mod[i, i] <- 0
-        }
-        return(tempo$v %*% Diag.mod %*% t(tempo$u))
-    }else{
-        return(solve(mat))
-    }
+names(data1) <- NULL # names solved -> to do not be disturbed by names
+names(data2) <- NULL # names solved -> to do not be disturbed by names
+if(any(data1 %in% data2)){
+any.id.element <- TRUE
+same.elements.pos1 <- which(data1 %in% data2)
+same.elements.match1 <- match(data1, data2)
 }
-
-
-######## fun_mat_fill() #### fill the empty half part of a symmetric square matrix
-
-
-fun_mat_fill <- function(mat, empty.cell.string = 0, warn.print = FALSE){
-    # AIM
-    # detect the empty half part of a symmetric square matrix (either topleft, topright, bottomleft or bottomright)
-    # fill this empty half part using the other symmetric half part of the matrix
-    # WARNINGS
-    # a plot verification using fun_gg_heatmap() is recommanded
-    # ARGUMENTS:
-    # mat: a numeric or character square matrix with the half part (according to the grand diagonal) filled with NA (any kind of matrix), "0" (character matrix) or 0 (numeric matrix) exclusively (not a mix of 0 and NA in the empty part)
-    # empty.cell.string: a numeric, character or NA (no quotes) indicating what empty cells are filled with
-    # warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
-    # RETURN
-    # a list containing:
-    # $mat: the filled matrix
-    # $warn: the warning messages. Use cat() for proper display. NULL if no warning
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # mat1 = matrix(c(1,NA,NA,NA, 0,2,NA,NA, NA,3,4,NA, 5,6,7,8), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = NA, warn.print = TRUE) # bottomleft example
-    # mat1 = matrix(c(1,1,1,2, 0,2,3,0, NA,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = NA, warn.print = TRUE) # error example
-    # mat1 = matrix(c(1,1,1,2, 0,2,3,0, NA,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # bottomright example
-    # mat1 = matrix(c(1,1,1,2, "a",2,3,NA, "a","a",0,0, "a","a","a",0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = "a", warn.print = TRUE) # topright example
-    # mat1 = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # topleft example
-    # mat1 = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # error example
-    # DEBUGGING
-    # mat = matrix(c(1,NA,NA,NA, 0,2,NA,NA, NA,3,4,NA, 5,6,7,8), ncol = 4) ; empty.cell.string = NA ; warn.print = TRUE # for function debugging
-    # mat = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; empty.cell.string = 0 ; warn.print = TRUE # for function debugging # topleft example
-    # mat = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; empty.cell.string = NA ; warn.print = TRUE # for function debugging # topleft example
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = mat, class = "matrix", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = empty.cell.string, class = "vector", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # argument checking without fun_check()
-    if(ncol(mat) != nrow(mat)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A SQUARE MATRIX")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (base::mode(mat) %in% c("numeric", "character"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A NUMERIC OR CHARACTER MATRIX")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(nrow(mat) == 1L & ncol(mat) == 1L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT CANNOT BE A SQUARE MATRIX MADE OF A SINGLE CASE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(ifelse(is.na(empty.cell.string), ! any(is.na(mat)), ! any(mat == empty.cell.string, na.rm = TRUE))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MATRIX MUST HAVE CELLS WITH THE EMPTY STRING SPECIFIED IN empty.cell.string ARGUMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking without fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    list.diag <- vector("list", length = nrow(mat) - 1) 
-    for(i1 in 1:(nrow(mat) - 1)){
-        list.diag[[i1]] <- numeric(length = nrow(mat) - i1) # list made of zero
-    }
-    sector <- c("topleft", "topright", "bottomright", "bottomleft")
-    diag.scan <-c( # same order as sector. Recover each diag from center to corner
-        "mat[as.matrix(as.data.frame(list(1:(nrow(mat) - i2), (ncol(mat) -i2):1), stringsAsFactors = TRUE))]", # topleft part
-        "mat[as.matrix(as.data.frame(list(1:(nrow(mat) - i2), (1:ncol(mat))[-(1:i2)]), stringsAsFactors = TRUE))]", # topright part
-        "mat[as.matrix(as.data.frame(list((1 + i2):nrow(mat), ncol(mat):(1 + i2)), stringsAsFactors = TRUE))]", # bottomright part
-        "mat[as.matrix(as.data.frame(list((1 + i2):nrow(mat), 1:(ncol(mat) -i2)), stringsAsFactors = TRUE))]" # bottomleft part
-    )
-    # empty part detection
-    empty.sector <- NULL
-    full.sector <- NULL
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    for(i1 in 1:length(sector)){
-        tempo.list.diag <- list.diag
-        for(i2 in 1:(nrow(mat) - 1)){
-            tempo.list.diag[[i2]] <- eval(parse(text = diag.scan[i1]))
-            if(ifelse(is.na(empty.cell.string), ! all(is.na(tempo.list.diag[[i2]])), ! (all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = TRUE) & ! (is.na(all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE)))))){ # I had to add this ! (is.na(all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE))) because all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE) gives NA and not FALSE if one NA in tempo.list.diag[[i2]] -> not good for if()
-                full.sector <- c(full.sector, sector[i1])
-                break
-            }
-        }
-        if(i2 == nrow(mat) - 1){
-            if(all(unlist(lapply(tempo.list.diag, FUN = function(x){if(is.na(empty.cell.string)){is.na(x)}else{x == empty.cell.string}})), na.rm = TRUE)){
-                empty.sector <- c(empty.sector, sector[i1])
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") EMPTY SECTOR DETECTED ON THE ", toupper(sector[i1]), " CORNER, FULL OF ", empty.cell.string)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": THE ", toupper(sector[i1]), " SECTOR, DETECTED AS EMPTY, IS NOT? DIFFERENT VALUES IN THIS SECTOR:\n", paste(names(table(unlist(tempo.list.diag), useNA = "ifany")), collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-    }
-    # end empty part detection
-    if(length(empty.sector) == 0L){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") ACCORDING TO empty.cell.string ARGUMENT (", empty.cell.string, "), mat ARGUMENT MATRIX HAS ZERO EMPTY HALF PART")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }else{
-        if(length(empty.sector) > 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ACCORDING TO empty.cell.string ARGUMENT (", empty.cell.string, "), mat ARGUMENT MATRIX HAS MORE THAN ONE EMPTY HALF PART (ACCORDING TO THE GRAND DIAGONAL): ", paste(empty.sector, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(any(full.sector %in% empty.sector, na.rm = TRUE)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE FUNCTION HAS DETECTED EMPTY AND NON EMPTY HALF PART IN THE SAME SECTOR: ", paste(full.sector[full.sector %in% empty.sector], collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(length(empty.sector) + length(full.sector)!= 4){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE FUNCTION HAS DETECTED MORE OR LESS SECTORS THAN 4:\nHALF SECTORS:", paste(empty.sector, collapse = " "), "\nFULL SECTORS:", paste(full.sector, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") ", toupper(empty.sector), " SECTOR HAS BEEN COMPLETED TO BECOME SYMMETRICAL")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        # matrix filling
-        for(i2 in 1:(nrow(mat) - 1)){
-            if(empty.sector == "topleft"){
-                eval(parse(text = paste0(diag.scan[1], " <- ", diag.scan[3])))
-            }else if(empty.sector == "topright"){
-                eval(parse(text = paste0(diag.scan[2], " <- ", diag.scan[4])))
-            }else if(empty.sector == "bottomright"){
-                eval(parse(text = paste0(diag.scan[3], " <- ", diag.scan[1])))
-            }else if(empty.sector == "bottomleft"){
-                eval(parse(text = paste0(diag.scan[4], " <- ", diag.scan[2])))
-            }
-        }
-        # end matrix filling
-    }
-    if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    return(list(mat = mat, warn = warn))
+if(any(data2 %in% data1)){
+any.id.element <- TRUE
+same.elements.pos2 <- which(data2 %in% data1)
+same.elements.match2 <- match(data2, data1)
 }
-
-
-######## fun_permut() #### progressively breaks a vector order
-
-
-fun_permut <- function(
-    data1, 
-    data2 = NULL, 
-    n = NULL, 
-    seed = NULL, 
-    print.count = 10, 
-    text.print = "", 
-    cor.method = "spearman", 
-    cor.limit = 0.2, 
-    warn.print = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # reorder the elements of the data1 vector by flipping 2 randomly selected  consecutive positions either:
-    # 1) n times (when n is precised) or
-    # 2) until the correlation between data1 and data2 decreases down to the cor.limit (0.2 by default). See cor.limit below to deal with negative correlations
-    # Example of consecutive position flipping: ABCD -> BACD -> BADC, etc.
-    # designed for discrete values, but worls also for continuous values
-    # WARNINGS
-    # see # https://www.r-bloggers.com/strategies-to-speedup-r-code/ for code speedup
-    # the random switch of non consecutive positions (ABCD -> DBCA for instance) does not work very well as the correlation is quickly obtained but the initial vector structure is mainly kept (no much order). Ths code would be: pos <- ini.pos[1:2] ; pos <- sample.int(n = n , size = 2, replace = FALSE) ; tempo.pos[pos] <- tempo.pos[rev(pos)]
-    # ARGUMENTS
-    # data1: a vector of at least 2 elements. Must be numeric if data2 is specified
-    # data2: a numeric vector of same length as data1
-    # n: number of times "flipping 2 randomly selected consecutive positions". Ignored if data2 is specified
-    # seed: integer number used by set.seed(). Write NULL if random result is required, an integer otherwise. BEWARE: if not NULL, fun_permut() will systematically return the same result when the other parameters keep the same settings
-    # print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
-    # text.print: optional message to add to the working progress message every print.count loop
-    # cor.method: correlation method. Either "pearson", "kendall" or "spearman". Ignored if data2 is not specified
-    # cor.limit: a correlation limit (between 0 and 1). Ignored if data2 is not specified. Compute the correlation between data1 and data2, permute the data1 values, and stop the permutation process when the correlation between data1 and data2 decreases down below the cor limit value (0.2 by default). If cor(data1, data2) is negative, then -cor.limit is used and the process stops until the correlation between data1 and data2 increases up over cor.limit (-0.2 by default). BEWARE: write a positive cor.limit even if cor(data1, data2) is known to be negative. The function will automatically uses -cor.limit. If the initial correlation is already below cor.limit (positive correlation) or over -cor.limit (negative correlation), then the data1 value positions are completely randomized (correlation between data1 and data2 is expected to be 0)
-    # warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # RETURN
-    # a list containing:
-    # $data: the modified vector
-    # $warn: potential warning messages (in case of negative correlation when data2 is specified). NULL if non warning message
-    # $cor: a spearman correlation between the initial positions (1:length(data1) and the final positions if data2 is not specified and the final correlation between data1 and data2 otherwise, according to cor.method
-    # $count: the number of loops used
-    # REQUIRED PACKAGES
-    # lubridate
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # fun_round()
-    # EXAMPLES
-    # example (1) showing that for loop, used in fun_permut(), is faster than while loop
-    # ini.time <- as.numeric(Sys.time()) ; count <- 0 ; for(i0 in 1:1e9){count <- count + 1} ; tempo.time <- as.numeric(Sys.time()) ; tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time)) ; tempo.lapse
-    # example (2) showing that for loop, used in fun_permut(), is faster than while loop
-    # ini.time <- as.numeric(Sys.time()) ; count <- 0 ; while(count < 1e9){count <- count + 1} ; tempo.time <- as.numeric(Sys.time()) ; tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time)) ; tempo.lapse
-    # fun_permut(data1 = LETTERS[1:5], data2 = NULL, n = 100, seed = 1, print.count = 10, text.print = "CPU NB 4")
-    # fun_permut(data1 = 101:110, data2 = 21:30, seed = 1, print.count = 1e4, text.print = "", cor.method = "spearman", cor.limit = 0.2)
-    # a way to use the cor.limit argument just considering data1
-    # obs1 <- 101:110 ; fun_permut(data1 = obs1, data2 = obs1, seed = 1, print.count = 10, cor.method = "spearman", cor.limit = 0.2)
-    # fun_permut(data1 = 1:1e3, data2 = 1e3:1, seed = 1, print.count = 1e6, text.print = "", cor.method = "spearman", cor.limit = 0.7)
-    # fun_permut(data1 = 1:1e2, data2 = 1e2:1, seed = 1, print.count = 1e3, cor.limit = 0.5)
-    # fun_permut(data1 = c(0,0,0,0,0), n = 5, data2 = NULL, seed = 1, print.count = 1e3, cor.limit = 0.5)
-    # DEBUGGING
-    # data1 = LETTERS[1:5] ; data2 = NULL ; n = 1e6 ; seed = NULL ; print.count = 1e3 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
-    # data1 = LETTERS[1:5] ; data2 = NULL ; n = 10 ; seed = 22 ; print.count = 10 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
-    # data1 = 101:110 ; data2 = 21:30 ; n = 10 ; seed = 22 ; print.count = 10 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
-    # data1 = 1:1e3 ; data2 = 1e3:1 ; n = 20 ; seed = 22 ; print.count = 1e6 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.5 ; warn.print = TRUE ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_pack", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_round", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data1, class = "vector", fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & length(data1) < 2){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A VECTOR OF MINIMUM LENGTH 2. HERE IT IS: ", length(data1))
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(data2)){
-        tempo <- fun_check(data = data1, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": data1 MUST BE A NUMERIC VECTOR IF data2 ARGUMENT IS SPECIFIED")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-        tempo <- fun_check(data = data2, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
-        if(length(data1) != length(data2)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": data1 AND data2 MUST BE VECTOR OF SAME LENGTH. HERE IT IS ", length(data1)," AND ", length(data2))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else if(is.null(n)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT CANNOT BE NULL IF data2 ARGUMENT IS NULL")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(n)){
-        tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(seed)){
-        tempo <- fun_check(data = seed, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = text.print, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = cor.method, options = c("pearson", "kendall", "spearman"), length =1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = cor.limit, class = "vector", mode = "numeric", prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # package checking
-    fun_pack(req.package = "lubridate", lib.path = lib.path)
-    # end package checking
-    # main code
-    # code that protects set.seed() in the global environment
-    # see also Protocol 100-rev0 Parallelization in R.docx
-    if(exists(".Random.seed", envir = .GlobalEnv)){ # if .Random.seed does not exists, it means that no random operation has been performed yet in any R environment
-        tempo.random.seed <- .Random.seed
-        on.exit(assign(".Random.seed", tempo.random.seed, env = .GlobalEnv))
-    }else{
-        on.exit(set.seed(NULL)) # inactivate seeding -> return to complete randomness
-    }
-    set.seed(seed)
-    # end code that protects set.seed() in the global environment
-    ini.date <- Sys.time() # time of process begin, converted into seconds
-    ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
-    ini.pos <- 1:length(data1) # positions of data1 before permutation loops
-    tempo.pos <- ini.pos # positions of data1 that will be modified during loops
-    # pos.selec.seq <- ini.pos[-length(data1)] # selection of 1 position in initial position, without the last because always up permutation (pos -> pos+1 & pos+1 -> pos)
-    pos.selec.seq.max <- length(ini.pos) - 1 # max position (used by sample.int() function). See  below for - 1
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    count <- 0
-    round <- 0
-    BREAK <- FALSE
-    tempo.cor <- 0
-    if(is.null(data2)){
-        if(length(table(data1)) == 1L){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data1 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data1)))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
-        }else{
-            if(print.count > n){
-                print.count <- n
-            }
-            cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP OF ", n, " LOOPS INITIATED | LOOP COUNT: ", format(count, big.mark=",")))
-            print.count.loop <- logical(length = print.count)
-            print.count.loop[length(print.count.loop)] <- TRUE # not this to avoid long vector, but not forget to reset during printing: print.count.loop[(1:trunc(n / print.count) * print.count)] <- TRUE # counter to speedup
-            count.loop <- 0
-            pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-            tempo.date.loop <- Sys.time()
-            tempo.time.loop <- as.numeric(tempo.date.loop)
-            for(i3 in 1:n){
-                count.loop <- count.loop + 1
-                pos2 <- pos[count.loop] # selection of 1 position
-                tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                if(print.count.loop[count.loop]){
-                    count.loop <- 0
-                    pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
-                    tempo.time <- as.numeric(Sys.time())
-                    tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
-                    final.loop <- (tempo.time - tempo.time.loop) / i3 * n # expected duration in seconds
-                    final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
-                    cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP ", i3, " / ", n, " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
-                }
-            }
-            count <- count + n # out of the loop to speedup
-            cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP ENDED | LOOP COUNT: ", format(count, big.mark=",")))
-            cat("\n\n")
-        }
-    }else{
-        if(length(table(data1)) == 1L){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data1 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data1)))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
-            tempo.cor <- 1
-        }else if(length(table(data2)) == 1L){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data2 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data2)))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
-            tempo.cor <- 1
-        }else{
-            cor.ini <- cor(x = data1, y = data2, use = "pairwise.complete.obs", method = cor.method)
-            tempo.cor <- cor.ini # correlation that will be modified during loops
-            neg.cor <- FALSE
-            if(tempo.cor < 0){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") INITIAL ", toupper(cor.method), " CORRELATION BETWEEN data1 AND data2 HAS BEEN DETECTED AS NEGATIVE: ", tempo.cor, ". THE LOOP STEPS WILL BE PERFORMED USING POSITIVE CORRELATIONS BUT THE FINAL CORRELATION WILL BE NEGATIVE")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
-                neg.cor <- TRUE
-                tempo.cor <- abs(tempo.cor)
-                cor.ini <- abs(cor.ini)
-            }
-            if(tempo.cor < cor.limit){ # randomize directly all the position to be close to correlation zero
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") INITIAL ABSOLUTE VALUE OF THE ", toupper(cor.method), " CORRELATION ", fun_round(tempo.cor), " BETWEEN data1 AND data2 HAS BEEN DETECTED AS BELOW THE CORRELATION LIMIT PARAMETER ", cor.limit, "\nTHE data1 SEQUENCE HAS BEEN COMPLETELY RANDOMIZED TO CORRESPOND TO CORRELATION ZERO")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
-                for(i4 in 1:5){ # done 5 times to be sure of the complete randomness
-                    tempo.pos <- sample(x = tempo.pos, size = length(tempo.pos), replace = FALSE)
-                }
-                count <- count + 5 # out of the loop to speedup
-            }else{
-                # smallest correlation decrease
-                count <- count + 1 # 1 and not 0 because already 1 performed just below
-                pos <- sample.int(n = pos.selec.seq.max , size = 1, replace = TRUE) # selection of 1 position # pos.selec.seq.max  because selection of 1 position in initial position, without the last because always up permutation (pos -> pos+1 & pos+1 -> pos)
-                tempo.pos[c(pos + 1, pos)] <- tempo.pos[c(pos, pos + 1)]
-                tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
-                smallest.cor.dec <- cor.ini - tempo.cor
-                # end smallest correlation decrease
-                # going out of tempo.cor == cor.ini
-                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "CORRELATION DECREASE AFTER A SINGLE PERMUTATION: ", fun_round(smallest.cor.dec, 4)))
-                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP -> GOING OUT FROM EQUALITY | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
-                print.count.loop <- logical(length = print.count)
-                print.count.loop[length(print.count.loop)] <- TRUE # counter to speedup
-                count.loop <- 0 # 
-                pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                tempo.date.loop <- Sys.time()
-                tempo.time.loop <- as.numeric(tempo.date.loop)
-                while(tempo.cor == cor.ini){ # to be out of equality between tempo.cor and cor.ini at the beginning (only valid for very long vector)
-                    count <- count + 1
-                    count.loop <- count.loop + 1
-                    pos2 <- pos[count.loop]
-                    tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                    tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
-                    if(print.count.loop[count.loop]){
-                        count.loop <- 0
-                        pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
-                        tempo.time <- as.numeric(Sys.time())
-                        tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
-                        cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP", format(count.loop, big.mark=","), " / ? | COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TIME SPENT: ", tempo.lapse))
-                    }
-                }
-                tempo.time <- as.numeric(Sys.time())
-                tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP END | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TOTAL SPENT TIME: ", tempo.lapse))
-                if(tempo.cor < cor.limit){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE FIRST FOR & WHILE LOOP STEPS HAVE BEEN TOO FAR AND SUBSEQUENT LOOP STEPS WILL NOT RUN")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-                # end going out of tempo.cor == cor.ini
-                # estimation of the average correlation decrease per loop on x loops and for loop execution
-                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE/FOR LOOPS INITIATION | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
-                count.est <- 1e5
-                first.round <- TRUE
-                GOBACK <- FALSE
-                while(tempo.cor > cor.limit){
-                    round <- round + 1
-                    # estimation step
-                    if(first.round == TRUE){
-                        first.round <- FALSE
-                        cor.dec.per.loop <- numeric(length = 5)
-                        loop.nb.est <- Inf
-                        cor.est.ini <- tempo.cor
-                        cor.est <- numeric(length = 5)
-                        for(i6 in 1:5){ # connected to cor.dec.per.loop
-                            tempo.pos.est <- tempo.pos
-                            pos <- sample.int(n = pos.selec.seq.max , size = count.est, replace = TRUE) # selection of n position
-                            for(i7 in 1:count.est){
-                                pos2 <- pos[i7] # selection of 1 position
-                                tempo.pos.est[c(pos2 + 1, pos2)] <- tempo.pos.est[c(pos2, pos2 + 1)]
-                            }
-                            tempo.cor.est <- abs(cor(x = data1[tempo.pos.est], y = data2, use = "pairwise.complete.obs", method = cor.method))
-                            cor.est[i6] <- tempo.cor.est
-                            tempo.cor.dec.per.loop <- (cor.est.ini - tempo.cor.est) / count.est # correlation decrease per loop
-                            if(is.na(tempo.cor.dec.per.loop) | ! is.finite(tempo.cor.dec.per.loop)){
-                                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2\ncor.est.ini: ", cor.est.ini, "\ntempo.cor.est: ", tempo.cor.est)
-                                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                            }
-                            cor.dec.per.loop[i6] <- tempo.cor.dec.per.loop
-                        }
-                        cor.est <- cor.est[which.max(cor.dec.per.loop)] # max to avoid to go to far with for loop (tempo.cor below tempo.limit)
-                        cor.dec.per.loop <- max(cor.dec.per.loop, na.rm = TRUE) # max to avoid to go to far with for loop (tempo.cor below tempo.limit)
-                        loop.nb.est <- round((tempo.cor - cor.limit) / cor.dec.per.loop)
-                    }else{
-                        if(GOBACK == TRUE){
-                            loop.nb.est <- round(loop.nb.est / 2)
-                        }else{
-                            cor.dec.per.loop <- (cor.ini - tempo.cor) / count
-                            loop.nb.est <- round((tempo.cor - cor.limit) / cor.dec.per.loop)
-                        }
-                    }
-                    # end estimation step
-                    # loop step
-                    if(is.na(loop.nb.est) | ! is.finite(loop.nb.est)){
-                        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1\nloop.nb.est: ", loop.nb.est, "\ncor.ini: ", cor.ini, "\ntempo.cor: ", tempo.cor, "\ncor.limit: ", cor.limit, "\ncor.dec.per.loop: ", cor.dec.per.loop)
-                        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                    }else if(loop.nb.est > 1e4){ # below -> leave the while loop
-                        tempo.pos.secu <- tempo.pos
-                        count.secu <- count
-                        tempo.cor.secu <- tempo.cor
-                        cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "INITIAL SETTINGS BEFORE ROUND: ", round, " | LOOP COUNT: ", format(count, big.mark=","), " | GO BACK: ", GOBACK, " | LOOP NUMBER ESTIMATION: ", format(loop.nb.est, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
-                        print.count.loop <- logical(length = print.count)
-                        print.count.loop[length(print.count.loop)] <- TRUE # not this to avoid long vector, but not forget to reset during printing: print.count.loop[(1:trunc(n / print.count) * print.count)] <- TRUE # counter to speedup
-                        count.loop <- 0
-                        pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                        tempo.date.loop <- Sys.time()
-                        tempo.time.loop <- as.numeric(tempo.date.loop)
-                        for(i6 in 1:loop.nb.est){
-                            count.loop <- count.loop + 1
-                            pos2 <- pos[count.loop] # selection of 1 position
-                            tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                            if(print.count.loop[count.loop]){
-                                count.loop <- 0
-                                pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
-                                tempo.time <- as.numeric(Sys.time())
-                                tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
-                                final.loop <- (tempo.time - tempo.time.loop) / i6 * loop.nb.est # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
-                                final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
-                                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP | ROUND ", round, " | LOOP: ", format(i6, big.mark=","), " / ", format(loop.nb.est, big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
-                            }
-                        }
-                        count <- count + loop.nb.est # out of the loop to speedup
-                        tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
-                        if(tempo.cor > tempo.cor.secu | ((tempo.cor - cor.limit) < 0 & abs(tempo.cor - cor.limit) > smallest.cor.dec * round(log10(max(ini.pos, na.rm = TRUE))))){
-                            GOBACK <- TRUE
-                            tempo.pos <- tempo.pos.secu
-                            count <- count.secu
-                            tempo.cor <- tempo.cor.secu
-                        }else{
-                            GOBACK <- FALSE
-                        }
-                    }else{
-                        cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FINAL WHILE LOOP | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
-                        print.count.loop <- logical(length = print.count)
-                        print.count.loop[length(print.count.loop)] <- TRUE # counter to speedup
-                        count.loop <- 0 # 
-                        pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                        tempo.cor.loop <- tempo.cor
-                        tempo.date.loop <- Sys.time()
-                        tempo.time.loop <- as.numeric(tempo.date.loop)
-                        while(tempo.cor > cor.limit){
-                            count <- count + 1
-                            count.loop <- count.loop + 1
-                            pos2 <- pos[count.loop]
-                            tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
-                            tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
-                            if(print.count.loop[count.loop]){
-                                count.loop <- 0
-                                pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
-                                tempo.time <- as.numeric(Sys.time())
-                                tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
-                                final.loop <- (tempo.time - tempo.time.loop) / (tempo.cor.loop - tempo.cor) * (tempo.cor - cor.limit) # expected duration in seconds # tempo.cor.loop - tempo.cor always positive and tempo.cor decreases progressively starting from tempo.cor.loop
-                                final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
-                                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE LOOP | LOOP NB: ", format(count.loop, big.mark=","), " | COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
-                            }
-                        }
-                    }
-                }
-                tempo.time <- as.numeric(Sys.time())
-                tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-                cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE/FOR LOOPS END | LOOP COUNT: ", format(count, big.mark=","), " | NB OF ROUNDS: ", round, " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TOTAL SPENT TIME: ", tempo.lapse))
-            }
-            tempo.cor <- ifelse(neg.cor == TRUE, -tempo.cor, tempo.cor)
-        }
-    }
-    cat("\n\n")
-    if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE), add = TRUE)
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    output <- list(data = data1[tempo.pos], warn = warn, cor = if(is.null(data2)){cor(ini.pos, tempo.pos, method = "spearman")}else{tempo.cor}, count = count)
-    return(output)
+if(any.id.element == TRUE){
+common.elements <- unique(c(data1[same.elements.pos1], data2[same.elements.pos2]))
 }
-
-
-######## fun_slide() #### return a computation made on a vector using a sliding window
-
-
-fun_slide <- function(
-    data, 
-    window.size, 
-    step, 
-    from = NULL, 
-    to = NULL, 
-    fun, 
-    args = NULL, 
-    boundary = "left", 
-    parall = FALSE, 
-    thread.nb = NULL, 
-    print.count = 100, 
-    res.path = NULL, 
-    lib.path = NULL, 
-    verbose = TRUE, 
-    cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
-){
-    # AIM
-    # return a computation made on a vector using a sliding window
-    # WARNINGS
-    # The function uses two strategies, depending on the amout of memory required which depends on the data, window.size and step arguments. The first one uses lapply(), is generally fast but requires lots of memory. The second one uses a parallelized loop. The choice between the two strategies is automatic if parall argument is FALSE, and is forced toward parallelization if parall argument is TRUE
-    # The parall argument forces the parallelization, which is convenient when the data argument is big, because the lapply() function is sometimes slower than the parallelization
-    # Always use the env argument when fun_slide() is used inside functions
-    # ARGUMENTS
-    # data: vector, matrix, table or array of numeric values (mode must be numeric). Inf not allowed. NA will be removed before computation
-    # window.size: single numeric value indicating the width of the window sliding across data (in the same unit as data value)
-    # step: single numeric value indicating the step between each window (in the same unit as data value). Cannot be larger than window.size
-    # from: value of the left boundary of the first sliding window. If NULL, min(data) is used. The first window will strictly have from or min(data) as left boundary
-    # to: value of the right boundary of the last sliding window. If NULL, max(data) is used. Warning: (1) the final last window will not necessary have to|max(data) as right boundary. In fact the last window will be the one that contains to|max(data) for the first time, i.e., min[from|min(data) + window.size + n * step >= to|max(data)]; (2) In fact, the >= in min[from|min(data) + window.size + n * step >= to|max(data)] depends on the boundary argument (>= for "right" and > for "left"); (3) to have the rule (1) but for the center of the last window, use to argument as to = to|max(data) + window.size / 2
-    # fun: function or character string (without brackets) indicating the name of the function to apply in each window. Example: fun = "mean", or fun = mean
-    # args: character string of additional arguments of fun (separated by a comma between the quotes). Example args = "na.rm = TRUE" for fun = mean. Ignored if NULL
-    # boundary: either "left" or "right". Indicates if the sliding window includes values equal to left boundary and exclude values equal to right boundary ("left") or the opposite ("right")
-    # parall: logical. Force parallelization ?
-    # thread.nb: numeric value indicating the number of threads to use if ever parallelization is required. If NULL, all the available threads will be used. Ignored if parall is FALSE
-    # print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
-    # res.path: character string indicating the absolute pathway where the parallelization log file will be created if parallelization is used. If NULL, will be created in the R current directory
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # verbose: logical. Display messages?
-    # cute.path: character string indicating the absolute path of the cute.R file. Will be remove when cute will be a package. Ignored if parall is FALSE
-    # RETURN
-    # a data frame containing
-    #$left : the left boundary of each window (in the unit of the data argument)
-    #$right : the right boundary of each window (in the unit of data argument)
-    #$center : the center of each window (in the unit of data argument)
-    #$value : the computed value by the fun argument in each window)
-    # REQUIRED PACKAGES
-    # lubridate
-    # parallel if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_get_message
-    # fun_pack()
-    # EXAMPLES
-    # fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "left")
-    # fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "right") # effect of boundary argument
-    # fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "left", parall = TRUE) # effect of parall argument
-    # DEBUGGING
-    # data = c(1:10, 100:110, 500) ; window.size = 5 ; step = 2 ; from = NULL ; to = NULL ; fun = length ; args = NULL ; boundary = "left" ; parall = FALSE ; thread.nb = NULL ; print.count = 100 ; res.path = NULL ; lib.path = NULL ; verbose = TRUE ; env = NULL ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
-    # data = lag.pos; window.size = window.size; step = step; fun = length; from = min(a$pos); to = max(a$pos)
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check", 
-        "fun_get_message", 
-        "fun_pack"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # arg with no default values
-    mandat.args <- c(
-        "data", 
-        "window.size", 
-        "step", 
-        "fun"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data, mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = window.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = step, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(from)){
-        tempo <- fun_check(data = from, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(to)){
-        tempo <- fun_check(data = to, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo1 <- fun_check(data = fun, class = "vector", mode = "character", length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = fun, class = "function", length = 1, fun.name = function.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": fun ARGUMENT MUST BE A FUNCTION OR A CHARACTER STRING OF THE NAME OF A FUNCTION")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(args)){
-        tempo <- fun_check(data = args, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = boundary, options = c("left", "right"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = parall, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(parall == TRUE){
-        if( ! is.null(thread.nb)){
-            tempo <- fun_check(data = thread.nb, typeof = "integer", double.as.integer.allowed = TRUE, neg.values = FALSE, length = 1, fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE & thread.nb < 1){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": thread.nb PARAMETER MUST EQUAL OR GREATER THAN 1: ", thread.nb)
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(res.path)){
-        tempo <- fun_check(data = res.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = verbose, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = cute.path, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # new environment
-    env.name <- paste0("env", as.numeric(Sys.time()))
-    if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
-        tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        assign(env.name, new.env())
-        assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
-    }
-    # end new environment
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "data", 
-        "window.size", 
-        "step", 
-        # "from", # because can be NULL
-        # "to", # because can be NULL
-        "fun", 
-        # "args", # because can be NULL
-        "boundary", 
-        "parall", 
-        # "thread.nb", # because can be NULL
-        "print.count", 
-        # "res.path", # because can be NULL
-        # "lib.path", # because can be NULL
-        "verbose", 
-        "cute.path"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    # end warning initiation
-    # other checkings
-    if(length(data) == 0){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT CANNOT BE LENGTH 0")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(any( ! is.finite(data))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT CANNOT CONTAIN Inf VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if(step > window.size){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": step ARGUMENT MUST BE LOWER THAN window.size ARGUMENT\nstep: ", paste(step, collapse = " "), "\nwindow.size: ", paste(window.size, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-    }
-    if( ! is.null(res.path)){
-        if( ! all(dir.exists(res.path))){ # separation to avoid the problem of tempo$problem == FALSE and res.path == NA
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE res.path ARGUMENT DOES NOT EXISTS:\n", paste(res.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-    }else{
-        res.path <- getwd() # working directory
-    }
-    if( ! is.null(lib.path)){
-        if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
-        }
-    }
-    if(grepl(x = cute.path, pattern = "^http")){
-        tempo.error1 <- any(grepl(x = fun_get_message(data = "source(cute.path)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE)), pattern = "^[Ee]rror"))
-        tempo.error2 <- FALSE
-    }else{
-        tempo.error1 <- FALSE
-        tempo.error2 <- ! file.exists(cute.path)
-    }
-    if(tempo.error1 | tempo.error2){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(grepl(x = cute.path, pattern = "^http"), "URL", "FILE"), " PATH INDICATED IN THE cute.path PARAMETER DOES NOT EXISTS:\n", cute.path)
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    # end other checkings
-    # reserved word checking
-    # end reserved word checking
-    # end second round of checking and data preparation
-    # package checking
-    fun_pack(req.package = c("lubridate"), lib.path = lib.path)
-    fun_pack(req.package = c("parallel"), lib.path = lib.path)
-    # end package checking
-    # main code
-    if(verbose == TRUE){
-        cat("\nfun_slide JOB IGNITION\n")
-    }
-    ini.date <- Sys.time()
-    ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
-    fun <- match.fun(fun) # make fun <- get(fun) is fun is a function name written as character string of length 1
-    if(boundary == "left"){
-        left <- ">="
-        right <- "<"
-        right.last.wind <- ">"
-    }else if(boundary == "right"){
-        left <- ">"
-        right <- "<="
-        right.last.wind <- ">="
-    }else{
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    data <- as.vector(data)
-    data <- sort(data, na.last = NA) # NA removed
-    wind <- data.frame(left = seq(from = if(is.null(from)){min(data, na.rm = TRUE)}else{from}, to = if(is.null(to)){max(data, na.rm = TRUE)}else{to}, by = step), stringsAsFactors = TRUE)
-    wind <- data.frame(wind, right = wind$left + window.size, stringsAsFactors = TRUE)
-    wind <- data.frame(wind, center = (wind$left + wind$right) / 2, stringsAsFactors = TRUE)
-    if(all(wind$right < if(is.null(to)){max(data, na.rm = TRUE)}else{to})){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 2")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # The 3 next lines is for the rule of to argument with center (see to argument description)
-    # if(any(wind$center > max(data, na.rm = TRUE))){
-    # wind <- wind[ ! wind$center > max(data, na.rm = TRUE),]
-    # }
-    if(sum(get(right.last.wind)(wind$right, if(is.null(to)){max(data, na.rm = TRUE)}else{to}), na.rm = TRUE) > 1){  # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-        tempo.log <- get(right.last.wind)(wind$right, if(is.null(to)){max(data, na.rm = TRUE)}else{to}) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-        tempo.log[min(which(tempo.log), na.rm = TRUE)] <- FALSE # convert the first left boundary that goes above max(data, na.rm = TRUE) to FALSE to keep it (the next ones will be removed)
-        wind <- wind[ ! tempo.log,]
-    }
-    
-    # test if lapply can be used
-    if(parall == FALSE){
-        # new environment
-        env.name <- paste0("env", ini.time)
-        if(exists(env.name, where = -1)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            assign(env.name, new.env())
-            assign("wind", wind, envir = get(env.name, env = sys.nframe(), inherit = FALSE))
-            assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE))
-        }
-        # end new environment
-        tempo.message <- fun_get_message(data="lapply(X = wind$left, Y = data, FUN = function(X, Y){res <- get(left)(Y, X) ; return(res)})", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE), print.no = FALSE) # no env = sys.nframe(), inherit = FALSE in get(left) because look for function in the classical scope
-        rm(env.name) # optional, because should disappear at the end of the function execution
-    }else{
-        tempo.message <- "ERROR" # with this, force the parallelization by default
-    }
-    # end test if lapply can be used
-    if( ! any(grepl(x = tempo.message, pattern = "ERROR.*"))){
-        left.log <- lapply(X = wind$left, Y = data, FUN = function(X, Y){
-            res <- get(left)(Y, X) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-            return(res)
-        })
-        right.log <- lapply(X = wind$right, Y = data, FUN = function(X, Y){
-            res <- get(right)(Y, X) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-            return(res)
-        })
-        log <- mapply(FUN = "&", left.log, right.log, SIMPLIFY = FALSE)
-        output <- eval(parse(text = paste0("sapply(lapply(log, FUN = function(X){(data[X])}), FUN = fun", if( ! is.null(args)){paste0(", ", args)}, ")"))) # take the values of the data vector according to log (list of logical, each compartment of length(data)) and apply fun with args of fun
-        if(length(output) != nrow(wind)){
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 3")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            output <- data.frame(wind, value = output, stringsAsFactors = TRUE)
-        }
-    }else{
-        if(verbose == TRUE){
-            tempo.cat <- paste0("PARALLELIZATION INITIATED AT: ", ini.date)
-            cat(paste0("\n", tempo.cat, "\n"))
-        }
-        tempo.thread.nb = parallel::detectCores(all.tests = FALSE, logical = TRUE) # detect the number of threads
-        if( ! is.null(thread.nb)){
-            if(tempo.thread.nb < thread.nb){
-                thread.nb <- tempo.thread.nb
-                if(verbose == TRUE){
-                    tempo.cat <- paste0("ONLY: ", tempo.thread.nb, " THREADS AVAILABLE")
-                    cat(paste0("\n", tempo.cat, "\n"))
-                }
-            }
-        }else{
-            thread.nb <- tempo.thread.nb
-        }
-        if(verbose == TRUE){
-            tempo.cat <- paste0("NUMBER OF THREADS USED: ", thread.nb)
-            cat(paste0("\n    ", tempo.cat, "\n"))
-        }
-        Clust <- parallel::makeCluster(thread.nb, outfile = paste0(res.path, "/fun_slide_parall_log.txt")) # outfile to print or cat during parallelization (only possible in a file, outfile = "" do not work on windows)
-        cluster.list <- parallel::clusterSplit(Clust, 1:nrow(wind)) # split according to the number of cluster
-        if(verbose == TRUE){
-            tempo.cat <- paste0("SPLIT OF TEST NUMBERS IN PARALLELISATION:")
-            cat(paste0("\n    ", tempo.cat, "\n"))
-            str(cluster.list) # using print(str()) add a NULL below the result
-            cat("\n")
-        }
-        paral.output.list <- parallel::clusterApply( #
-            cl = Clust,
-            x = cluster.list,
-            function.name = function.name, 
-            data = data, 
-            FUN = fun, # because fun argument of clusterApply
-            args = args, 
-            thread.nb = thread.nb, 
-            print.count = print.count, 
-            wind = wind, 
-            left = left, 
-            right = right, 
-            res.path = res.path, 
-            lib.path = lib.path, 
-            verbose = verbose, 
-            env = env, 
-            cute.path = cute.path, 
-            fun = function(
-                x, 
-                function.name, 
-                data, 
-                FUN, 
-                args, 
-                thread.nb, 
-                print.count, 
-                wind, 
-                left, 
-                right, 
-                res.path, 
-                lib.path, 
-                verbose, 
-                env, 
-                cute.path
-            ){
-                # check again: very important because another R
-                process.id <- Sys.getpid()
-                cat(paste0("\nPROCESS ID ", process.id, " -> TESTS ", x[1], " TO ", x[length(x)], "\n"))
-                source(cute.path, local = .GlobalEnv)
-                fun_pack(req.package = "lubridate", lib.path = lib.path, load = TRUE) # load = TRUE to be sure that functions are present in the environment. And this prevent to use R.lib.path argument of fun_python_pack()
-                # end check again: very important because another R
-                ini.date <- Sys.time()
-                ini.time <- as.numeric(ini.date) # time of process begin, converted into 
-                output <- NULL
-                print.count.loop <- 0
-                for(i4 in 1:length(x)){
-                    print.count.loop <- print.count.loop + 1
-                    log <- get(left)(data, wind$left[x[i4]]) & get(right)(data, wind$right[x[i4]]) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-                    output <- c(output, eval(parse(text = paste0("FUN(data[log]", if( ! is.null(args)){paste0(", ", args)}, ")"))))
-                    if(verbose == TRUE){
-                        if(print.count.loop == print.count){
-                            print.count.loop <- 0
-                            tempo.time <- as.numeric(Sys.time())
-                            tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-                            final.loop <- (tempo.time - ini.time) / i4 * length(x) # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
-                            final.exp <- as.POSIXct(final.loop, origin = ini.date)
-                            cat(paste0("\nIN PROCESS ", process.id, " | LOOP ", format(i4, big.mark=","), " / ", format(length(x), big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
-                        }
-                        if(i4 == length(x)){
-                            tempo.time <- as.numeric(Sys.time())
-                            tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
-                            cat(paste0("\nPROCESS ", process.id, " ENDED | LOOP ", format(i4, big.mark=","), " / ", format(length(x), big.mark=","), " | TIME SPENT: ", tempo.lapse, "\n\n"))
-                        }
-                    }
-                }
-                wind <- wind[x, ]
-                if(length(output) != nrow(wind)){
-                    tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 4")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else{
-                    output <- data.frame(wind, value = output, stringsAsFactors = TRUE)
-                    return(output)
-                }
-            }
-        )
-        parallel::stopCluster(Clust)
-        # result assembly
-        output <- data.frame()
-        for(i2 in 1:length(paral.output.list)){ # compartment relatives to each parallelization
-            output <- rbind(output, paral.output.list[[i2]], stringsAsFactors = TRUE)
-        }
-        # end result assembly
-        if(nrow(output) != nrow(wind)){
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 5\nlength(output): ", length(output), "\nnrow(wind): ", nrow(wind))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            output <- output[order(output$left), ]
-        }
-    }
-    if(verbose == TRUE){
-        end.date <- Sys.time()
-        end.time <- as.numeric(end.date)
-        total.lapse <- round(lubridate::seconds_to_period(end.time - ini.time))
-        cat(paste0("fun_slide JOB END\n\nTIME: ", end.date, "\n\nTOTAL TIME LAPSE: ", total.lapse, "\n\n\n"))
-    }
-    return(output)
+if(identical(data1, data2)){
+identical.content <- TRUE
+same.order <- TRUE
+}else if(identical(sort(data1), sort(data2))){
+same.order <- FALSE
+order1 <- order(data1)
+order2 <- order(data2)
+}
+}
+output <- list(same.class = same.class, class = class, same.length = same.length, length = length, same.levels = same.levels, levels = levels, any.id.levels = any.id.levels, same.levels.pos1 = same.levels.pos1, same.levels.pos2 = same.levels.pos2, same.levels.match1 = same.levels.match1, same.levels.match2 = same.levels.match2, common.levels = common.levels, same.names = same.names, name = name, any.id.name = any.id.name, same.names.pos1 = same.names.pos1, same.names.pos2 = same.names.pos2, same.names.match1 = same.names.match1, same.names.match2 = same.names.match2, common.names = common.names, any.id.element = any.id.element, same.elements.pos1 = same.elements.pos1, same.elements.pos2 = same.elements.pos2, same.elements.match1 = same.elements.match1, same.elements.match2 = same.elements.match2, common.elements = common.elements, same.order = same.order, order1 = order1, order2 = order2, identical.object = identical.object, identical.content = identical.content)
+return(output)
 }
 
 
+######## fun_comp_2d() #### comparison of two 2D datasets (row & col names, dimensions, etc.)
 
 
-######## fun_codon2aa() #### convert codon to amino acid using standard genetic code
-
+fun_comp_2d <- function(data1, data2){
+# AIM
+# compare two 2D datasets of the same class or not. Check and report in a list if the 2 datasets have:
+# same class
+# common row names
+# common column names
+# same row number
+# same column number
+# potential identical rows between the 2 datasets
+# potential identical columns between the 2 datasets
+# WARNINGS
+# For data frames: content are compared after conversion of content into characters. This means that the comparison of the content of data frame, either row to row, or column to column, does not take into account the mode in the different columns. This concern the results in $any.id.row, $same.row.pos1, $same.row.pos2, $same.row.match1, $same.row.match2, $any.id.col, $same.row.col1, $same.row.col2, $same.col.match1, $same.col.match2 and $identical.content result
+# "TOO BIG FOR EVALUATION" returned in $same.row.pos1, $same.row.pos2, $same.row.match1 and $same.row.match2 when nrow(data1) * nrow(data2) > 1e6 and $any.id.row remains NULL
+# "TOO BIG FOR EVALUATION" returned in $same.row.col1, $same.row.col2, $same.col.match1 and $same.col.match2 when ncol(data1) * ncol(data2) > 1e6 and $any.id.col remains NULL
+# ARGUMENTS
+# data1: matrix, data frame or table
+# data2: matrix, data frame or table
+# RETURN
+# a list containing:
+# $same.class: logical. Are class identical ?
+# $class: classes of the 2 datasets (NULL otherwise)
+# $same.dim: logical. Are dimension identical ?
+# $dim: dimension of the 2 datasets (NULL otherwise)
+# $same.row.nb: logical. Are number of rows identical ?
+# $row.nb: nb of rows of the 2 datasets if identical (NULL otherwise)
+# $same.col.nb: logical. Are number of columns identical ?
+# $col.nb: nb of columns of the 2 datasets if identical (NULL otherwise)
+# $same.row.name: logical. Are row names identical ? NULL if no row names in the two 2D datasets
+# $row.name: name of rows of the 2 datasets if identical (NULL otherwise)
+# $any.id.row.name: logical. Is there any row names identical ? NULL if no row names in the two 2D datasets
+# $same.row.names.pos1: positions, in data1, of the row names identical in data2
+# $same.row.names.pos2: positions, in data2, of the row names identical in data1
+# $same.row.names.match1: positions, in data2, of the row names that match the row names in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.row.names.match2: positions, in data1, of the row names that match the row names in data2, as given by match(data1, data2) (NULL otherwise)
+# $common.row.names: common row names between data1 and data2 (can be a subset of $name or not). NULL if no common row names
+# $same.col.name: logical. Are column names identical ? NULL if no col names in the two 2D datasets
+# $col.name: name of columns of the 2 datasets if identical (NULL otherwise)
+# $any.id.col.name: logical. Is there any column names identical ? NULL if no col names in the two 2D datasets
+# $same.col.names.pos1: positions, in data1, of the column names identical in data2
+# $same.col.names.pos2: positions, in data2, of the column names identical in data1
+# $same.col.names.match1: positions, in data2, of the column names that match the column names in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.col.names.match2: positions, in data1, of the column names that match the column names in data2, as given by match(data1, data2) (NULL otherwise)
+# $common.col.names: common column names between data1 and data2 (can be a subset of $name or not). NULL if no common column names
+# $any.id.row: logical. is there identical rows (not considering row names)? NULL if nrow(data1) * nrow(data2) > 1e10
+# $same.row.pos1: positions, in data1, of the rows identical in data2 (not considering row names). Return "TOO BIG FOR EVALUATION" if nrow(data1) * nrow(data2) > 1e10
+# $same.row.pos2: positions, in data2, of the rows identical in data1 (not considering row names). Return "TOO BIG FOR EVALUATION" if nrow(data1) * nrow(data2) > 1e10
+# $same.row.match1: positions, in data2, of the rows that match the rows in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.row.match2: positions, in data1, of the rows that match the rows in data2, as given by match(data1, data2) (NULL otherwise)
+# $any.id.col: logical. is there identical columns (not considering column names)? NULL if ncol(data1) * ncol(data2) > 1e10
+# $same.col.pos1: position in data1 of the cols identical in data2 (not considering column names). Return "TOO BIG FOR EVALUATION" if ncol(data1) * ncol(data2) > 1e10
+# $same.col.pos2: position in data2 of the cols identical in data1 (not considering column names). Return "TOO BIG FOR EVALUATION" if ncol(data1) * ncol(data2) > 1e10
+# $same.col.match1: positions, in data2, of the columns that match the columns in data1, as given by match(data1, data2) (NULL otherwise)
+# $same.row.match2: positions, in data1, of the columns that match the columns in data2, as given by match(data1, data2) (NULL otherwise)
+# $identical.object: logical. Are objects identical (including row & column names)?
+# $identical.content: logical. Are content objects identical (identical excluding row & column names)?
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# none
+# EXAMPLES
+# obs1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = as.data.frame(matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])), stringsAsFactors = TRUE) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
+# obs1 = matrix(101:110, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
+# large matrices
+# obs1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; obs2 = matrix(as.integer((1:1e6)+1e6/5), ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; head(obs1) ; head(obs2) ; fun_comp_2d(obs1, obs2)
+# WARNING: when comparing content (rows, columns, or total), double and integer data are considered as different -> double(1) != integer(1)
+# obs1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; obs2 = matrix((1:1e6)+1e6/5, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; head(obs1) ; head(obs2) ; fun_comp_2d(obs1, obs2)
+# Matrices: same row conten tand same row names
+# obs1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4]))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
+# Matrices: same row content but not same row names -> works: same content is identified
+# obs1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; obs2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("x", "z", "y"), c(LETTERS[1:2], "k", LETTERS[5:4]))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
+# obs1 = t(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = t(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1 ; obs2 ; fun_comp_2d(obs1, obs2)
+# Data frames: same row content and same row names, not same mode between columns
+# obs1 = as.data.frame(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = as.data.frame(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1[, 5] <- as.character(obs1[, 5]) ; obs2[, 5] <- as.character(obs2[, 5]) ; obs1 ; obs2 ; str(obs1) ; str(obs2) ; fun_comp_2d(obs1, obs2)
+# Data frames: same row content but not same row names -> works: same content is identified
+# obs1 = as.data.frame(matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5]))) ; obs2 = as.data.frame(matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("x", "z", "y"), c(LETTERS[1:2], "k", LETTERS[5:4])))) ; obs1[, 5] <- as.character(obs1[, 5]) ; obs2[, 5] <- as.character(obs2[, 5]) ; obs1 ; obs2 ; str(obs1) ; str(obs2) ; fun_comp_2d(obs1, obs2)
+# DEBUGGING
+# data1 = matrix(1:10, ncol = 5) ; data2 = matrix(1:10, ncol = 5) # for function debugging
+# data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5) # for function debugging
+# data1 = matrix(1:15, byrow = TRUE, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# data1 = matrix(1:15, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# data1 = matrix(1:15, ncol = 5, dimnames = list(paste0("A", letters[1:3]), LETTERS[1:5])) ; data2 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# data1 = matrix(1:15, ncol = 5, dimnames = list(letters[1:3], LETTERS[1:5])) ; data2 = matrix(1:12, ncol = 4, dimnames = list(letters[1:3], LETTERS[1:4])) # for function debugging
+# data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(101:110, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) # for function debugging
+# data1 = data.frame(a = 1:3, b= letters[1:3], row.names = LETTERS[1:3], stringsAsFactors = TRUE) ; data2 = data.frame(A = 1:3, B= letters[1:3], stringsAsFactors = TRUE) # for function debugging
+# data1 = matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = as.data.frame(matrix(1:10, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])), stringsAsFactors = TRUE) # for function debugging
+# data1 = matrix(1:10, byrow = TRUE, ncol = 5, dimnames = list(letters[1:2], LETTERS[1:5])) ; data2 = matrix(c(1:5, 101:105, 6:10), byrow = TRUE, ncol = 5, dimnames = list(c("a", "z", "b"), c(LETTERS[1:2], "k", LETTERS[5:4]))) # for function debugging
+# data1 = table(Exp1 = c("A", "A", "A", "B", "B", "B"), Exp2 = c("A1", "B1", "A1", "C1", "C1", "B1")) ; data2 = data.frame(A = 1:3, B= letters[1:3], stringsAsFactors = TRUE) # for function debugging
+# data1 = matrix(1:1e6, ncol = 5, dimnames = list(NULL, LETTERS[1:5])) ; data2 = matrix((1:1e6)+1e6/5, ncol = 5, dimnames = list(NULL, LETTERS[1:5]))
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# argument checking
+if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A MATRIX, DATA FRAME OR TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (any(class(data2) %in% c("data.frame", "table")) | all(class(data2) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data2) %in% c("matrix", "data.frame", "table"))
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A MATRIX, DATA FRAME OR TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
+# end argument checking
+# main code
+same.class <- NULL
+class <- NULL
+same.dim <- NULL
+dim <- NULL
+same.row.nb <- NULL
+row.nb <- NULL
+same.col.nb <- NULL
+col.nb <- NULL
+same.row.name <- NULL
+row.name <- NULL
+any.id.row.name <- NULL
+same.row.names.pos1 <- NULL
+same.row.names.pos2 <- NULL
+same.row.names.match1 <- NULL
+same.row.names.match2 <- NULL
+common.row.names <- NULL
+same.col.name <- NULL
+any.id.col.name <- NULL
+same.col.names.pos1 <- NULL
+same.col.names.pos2 <- NULL
+same.col.names.match1 <- NULL
+same.col.names.match2 <- NULL
+common.col.names <- NULL
+col.name <- NULL
+any.id.row <- NULL
+same.row.pos1 <- NULL
+same.row.pos2 <- NULL
+same.row.match1 <- NULL
+same.row.match2 <- NULL
+any.id.col <- NULL
+same.col.pos1 <- NULL
+same.col.pos2 <- NULL
+same.col.match1 <- NULL
+same.col.match2 <- NULL
+identical.object <- NULL
+identical.content <- NULL
+if(identical(data1, data2) & (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
+same.class <- TRUE
+class <- class(data1)
+same.dim <- TRUE
+dim <- dim(data1)
+same.row.nb <- TRUE
+row.nb <- nrow(data1)
+same.col.nb <- TRUE
+col.nb <- ncol(data1)
+same.row.name <- TRUE
+row.name <- dimnames(data1)[[1]]
+any.id.row.name <- TRUE
+same.row.names.pos1 <- 1:row.nb
+same.row.names.pos2 <- 1:row.nb
+same.row.names.match1 <- 1:row.nb
+same.row.names.match2 <- 1:row.nb
+common.row.names <- dimnames(data1)[[1]]
+same.col.name <- TRUE
+col.name <- dimnames(data1)[[2]]
+any.id.col.name <- TRUE
+same.col.names.pos1 <- 1:col.nb
+same.col.names.pos2 <- 1:col.nb
+same.col.names.match1 <- 1:col.nb
+same.col.names.match2 <- 1:col.nb
+common.col.names <- dimnames(data1)[[2]]
+any.id.row <- TRUE
+same.row.pos1 <- 1:row.nb
+same.row.pos2 <- 1:row.nb
+same.row.match1 <- 1:row.nb
+same.row.match2 <- 1:row.nb
+any.id.col <- TRUE
+same.col.pos1 <- 1:col.nb
+same.col.pos2 <- 1:col.nb
+same.col.match1 <- 1:col.nb
+same.col.match2 <- 1:col.nb
+identical.object <- TRUE
+identical.content <- TRUE
+}else{
+identical.object <- FALSE
+if(all(class(data1) == "table") & length(dim(data1)) == 1L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT IS A 1D TABLE. USE THE fun_comp_1d FUNCTION")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(all(class(data2) == "table") & length(dim(data2)) == 1L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT IS A 1D TABLE. USE THE fun_comp_1d FUNCTION")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! identical(class(data1), class(data2))){
+same.class <- FALSE
+}else if( ! (any(class(data1) %in% c("data.frame", "table")) | all(class(data1) %in% c("matrix", "array")))){ # before R4.0.0, it was  ! any(class(data1) %in% c("matrix", "data.frame", "table"))
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 AND data2 ARGUMENTS MUST BE EITHER MATRIX, DATA FRAME OR TABLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+same.class <- TRUE
+class <- class(data1)
+}
+if( ! identical(dim(data1), dim(data2))){
+same.dim <- FALSE
+}else{
+same.dim <- TRUE
+dim <- dim(data1)
+}
+if( ! identical(nrow(data1), nrow(data2))){
+same.row.nb <- FALSE
+}else{
+same.row.nb <- TRUE
+row.nb <- nrow(data1)
+}
+if( ! identical(ncol(data1), ncol(data2))){
+same.col.nb <- FALSE
+}else{
+same.col.nb <- TRUE
+col.nb <- ncol(data1)
+}
+# row and col names
+if(is.null(dimnames(data1)) & is.null(dimnames(data2))){
+same.row.name <- NULL # but already NULL
+same.col.name <- NULL # but already NULL
+# other row names param remain NULL
+}else if((is.null(dimnames(data1)) & ! is.null(dimnames(data2))) | ( ! is.null(dimnames(data1)) & is.null(dimnames(data2)))){
+same.row.name <- FALSE
+same.col.name <- FALSE
+any.id.row.name <- FALSE
+any.id.col.name <- FALSE
+# other row names param remain NULL
+}else{
+# row names
+if(is.null(dimnames(data1)[[1]]) & is.null(dimnames(data2)[[1]])){
+same.row.name <- NULL # but already NULL
+# other row names param remain NULL
+}else if((is.null(dimnames(data1)[[1]]) & ! is.null(dimnames(data2)[[1]])) | ( ! is.null(dimnames(data1)[[1]]) & is.null(dimnames(data2)[[1]]))){
+same.row.name <- FALSE
+any.id.row.name <- FALSE
+# other row names param remain NULL
+}else if(identical(dimnames(data1)[[1]], dimnames(data2)[[1]])){
+same.row.name <- TRUE
+row.name <- dimnames(data1)[[1]]
+any.id.row.name <- TRUE
+same.row.names.pos1 <- 1:nrow(data1)
+same.row.names.pos2 <- 1:nrow(data1)
+same.row.names.match1 <- 1:nrow(data1)
+same.row.names.match2 <- 1:nrow(data1)
+common.row.names <- dimnames(data1)[[1]]
+}else{
+same.row.name <- FALSE
+any.id.row.name <- FALSE
+if(any(dimnames(data1)[[1]] %in% dimnames(data2)[[1]])){
+any.id.row.name <- TRUE
+same.row.names.pos1 <- which(dimnames(data1)[[1]] %in% dimnames(data2)[[1]])
+same.row.names.match1 <- match(dimnames(data1)[[1]], dimnames(data2)[[1]])
+}
+if(any(dimnames(data2)[[1]] %in% dimnames(data1)[[1]])){
+any.id.row.name <- TRUE
+same.row.names.pos2 <- which(dimnames(data2)[[1]] %in% dimnames(data1)[[1]])
+same.row.names.match2 <- match(dimnames(data2)[[1]], dimnames(data1)[[1]])
+}
+if(any.id.row.name == TRUE){
+common.row.names <- unique(c(dimnames(data1)[[1]][same.row.names.pos1], dimnames(data2)[[1]][same.row.names.pos2]))
+}
+}
+# col names
+if(is.null(dimnames(data1)[[2]]) & is.null(dimnames(data2)[[2]])){
+same.col.name <- NULL # but already NULL
+# other col names param remain NULL
+}else if((is.null(dimnames(data1)[[2]]) & ! is.null(dimnames(data2)[[2]])) | ( ! is.null(dimnames(data1)[[2]]) & is.null(dimnames(data2)[[2]]))){
+same.col.name <- FALSE
+any.id.col.name <- FALSE
+# other col names param remain NULL
+}else if(identical(dimnames(data1)[[2]], dimnames(data2)[[2]])){
+same.col.name <- TRUE
+col.name <- dimnames(data1)[[2]]
+any.id.col.name <- TRUE
+same.col.names.pos1 <- 1:ncol(data1)
+same.col.names.pos2 <- 1:ncol(data1)
+same.col.names.match1 <- 1:ncol(data1)
+same.col.names.match2 <- 1:ncol(data1)
+common.col.names <- dimnames(data1)[[2]]
+}else{
+same.col.name <- FALSE
+any.id.col.name <- FALSE
+if(any(dimnames(data1)[[2]] %in% dimnames(data2)[[2]])){
+any.id.col.name <- TRUE
+same.col.names.pos1 <- which(dimnames(data1)[[2]] %in% dimnames(data2)[[2]])
+same.col.names.match1 <- match(dimnames(data1)[[2]], dimnames(data2)[[2]])
+}
+if(any(dimnames(data2)[[2]] %in% dimnames(data1)[[2]])){
+any.id.col.name <- TRUE
+same.col.names.pos2 <- which(dimnames(data2)[[2]] %in% dimnames(data1)[[2]])
+same.col.names.match2 <- match(dimnames(data2)[[2]], dimnames(data1)[[2]])
+}
+if(any.id.col.name == TRUE){
+common.col.names <- unique(c(dimnames(data1)[[2]][same.col.names.pos1], dimnames(data2)[[2]][same.col.names.pos2]))
+}
+}
+}
+# identical row and col content
+if(all(class(data1) == "table")){
+data1 <- as.data.frame(matrix(data1, ncol = ncol(data1)), stringsAsFactors = FALSE) # conversion of table into data frame to facilitate inter class comparison
+}else if(all(class(data1) %in% c("matrix", "array"))){
+data1 <- as.data.frame(data1, stringsAsFactors = FALSE) # conversion of matrix into data frame to facilitate inter class comparison
+}else if(all(class(data1) == "data.frame")){
+# data1 <- data.frame(lapply(data1, as.character), stringsAsFactors = FALSE) # conversion of columns into characters
+}
+if(all(class(data2) == "table")){
+data2 <- as.data.frame(matrix(data2, ncol = ncol(data2)), stringsAsFactors = FALSE) # conversion of table into data frame to facilitate inter class comparison
+}else if(all(class(data2) %in% c("matrix", "array"))){
+data2 <- as.data.frame(data2, stringsAsFactors = FALSE) # conversion of matrix into data frame to facilitate inter class comparison
+}else if(all(class(data2) == "data.frame")){
+# data2 <- data.frame(lapply(data2, as.character), stringsAsFactors = FALSE) # conversion of columns into characters
+}
+row.names(data1) <- paste0("A", 1:nrow(data1))
+row.names(data2) <- paste0("A", 1:nrow(data2))
+if(same.col.nb == TRUE){ # because if not the same col nb, the row cannot be identical
+if(all(sapply(data1, FUN = typeof) == "integer") & all(sapply(data2, FUN = typeof) == "integer") & as.double(nrow(data1)) * nrow(data2) <= 1e10){ # fast method for integers (thus not data frames). as.double(nrow(data1)) to prevent integer overflow because R is 32 bits for integers
+tempo1 <- c(as.data.frame(t(data1), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
+tempo2 <- c(as.data.frame(t(data2), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
+same.row.pos1 <- which(tempo1 %in% tempo2)
+same.row.pos2 <- which(tempo2 %in% tempo1)
+same.row.match1 <- match(tempo1, tempo2)
+same.row.match2 <- match(tempo2, tempo1)
+}else if(as.double(nrow(data1)) * nrow(data2) <= 1e6){ # as.double(nrow(data1)) to prevent integer overflow because R is 32 bits for integers
+# inactivated because I would like to keep the mode during comparisons
+# if(col.nb <= 10){ # if ncol is not to big, the t() should not be that long
+# tempo1 <- c(as.data.frame(t(data1), stringsAsFactors = FALSE)) # conversion into list. This work fast with only integers (because 32 bits)
+# tempo2 <- c(as.data.frame(t(data2), stringsAsFactors = FALSE)) # conversion into list. 
+# same.row.pos1 <- which(tempo1 %in% tempo2)
+# same.row.pos2 <- which(tempo2 %in% tempo1)
+# same.row.match1 <- match(tempo1, tempo2)
+# same.row.match2 <- match(tempo2, tempo1)
+# }else{
+# very long computation
+same.row.pos1 <- logical(length = nrow(data1)) # FALSE by default
+same.row.pos1[] <- FALSE # security
+same.row.pos2 <- logical(length = nrow(data2)) # FALSE by default
+same.row.pos2[] <- FALSE # security
+same.row.match1 <- rep(NA, nrow(data1))
+same.row.match2 <- rep(NA, nrow(data2))
+for(i3 in 1:nrow(data1)){
+for(i4 in 1:nrow(data2)){
+tempo1 <- data1[i3, ]
+tempo2 <- data2[i4, ]
+rownames(tempo1) <- NULL # to have same row and column names
+colnames(tempo1) <- NULL # to have same row and column names
+rownames(tempo2) <- NULL # to have same row and column names
+colnames(tempo2) <- NULL # to have same row and column names
+if(identical(tempo1, tempo2)){
+same.row.pos1[i3] <- TRUE
+same.row.pos2[i4] <- TRUE
+same.row.match1[i3] <- i4
+same.row.match2[i4] <- i3
+}
+}
+}
+same.row.pos1 <- which(same.row.pos1)
+same.row.pos2 <- which(same.row.pos2)
+# }
+}else{
+same.row.pos1 <- "TOO BIG FOR EVALUATION"
+same.row.pos2 <- "TOO BIG FOR EVALUATION"
+same.row.match1 <- "TOO BIG FOR EVALUATION"
+same.row.match2 <- "TOO BIG FOR EVALUATION"
+}
 
-fun_codon2aa <- function(
-    data,
-    display = FALSE
-){
-    # AIM
-    # Convert codon to amino acid using standard genetic code indicated in https://en.wikipedia.org/wiki/DNA_and_RNA_codon_tables
-    # WARNINGS
-    # None
-    # ARGUMENTS
-    # data: single caracter string of three characters, or vector of three caracters, indicating the DNA codon (only "A", "T", "G" and "C" allowed). Case insensitive. Omitted if display argument is TRUE
-    # display: logical. Display the whole genetic table? if TRUE, override data
-    # RETURN
-    # The 1 letter uppercase amino acid of the submitted codon or the whole table if display argument is TRUE
-    # REQUIRED PACKAGES
-    # None
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # fun_check()
-    # EXAMPLE
-    # fun_codon2aa(data = "ATC", display = TRUE)
-    # see http
-    # DEBUGGING
-    # data = "atg" ; display = FALSE
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # arg with no default values
-    mandat.args <- c(
-        "data"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data, class = "vector", typeof = "character", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = display, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){ # normally no NA
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "data", 
-        "display"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    # end warning initiation
-    # other checkings
-    if(length(data) == 1L){
-        data <- unlist(strsplit(data, split = ""))
-    }else if(length(data) != 3L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A STRING OF THREE CHARACTERS OR A VECTOR OF THREE CHARACTERS, MADE OF \"A\", \"C\", \"G\", \"T\" ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! all(toupper(data) %in% c("A", "C", "G","T"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A STRING OF THREE CHARACTERS OR A VECTOR OF THREE CHARACTERS, MADE OF \"A\", \"C\", \"G\", \"T\" ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end other checkings
-    # reserved word checking
-    # end reserved word checking
-    # end second round of checking and data preparation
-    # package checking
-    # end package checking
-    # main code
-    # standard genetic code
-    sgc <- array(
-        c(
-            "F", "L", "I", "V",
-            "S", "P", "T", "A",
-            "Y", "H", "N", "D",
-            "C", "R", "S", "G",
-            
-            "F", "L", "I", "V",
-            "S", "P", "T", "A",
-            "Y", "H", "N", "D",
-            "C", "R", "S", "G",
-            
-            "L", "L", "I", "V",
-            "S", "P", "T", "A",
-            "stop", "Q", "K", "E",
-            "stop", "R", "R", "G",
-            
-            "L", "L", "M", "V",
-            "S", "P", "T", "A",
-            "stop", "Q", "K", "E",
-            "W", "R", "R", "G"
-        ), 
-        dim = c(4, 4, 4),
-        dimnames = list(
-            first = c("T", "C", "A", "G"), 
-            second = c("T", "C", "A", "G"), 
-            third = c("T", "C", "A", "G")
-        )
-    )
-    # end standard genetic code
-    if(display == TRUE){
-        output <- sgc
-    }else{
-        data <- toupper(data)
-        output <- eval(parse(text = paste0("sgc['", paste0(data, collapse = "','"), "']")))
-    }
-    return(output)
+names(same.row.pos1) <- NULL
+names(same.row.pos2) <- NULL
+if(all(is.na(same.row.pos1))){
+same.row.pos1 <- NULL
+}else{
+same.row.pos1 <- same.row.pos1[ ! is.na(same.row.pos1)]
+any.id.row <- TRUE
+}
+if(all(is.na(same.row.pos2))){
+same.row.pos2 <- NULL
+}else{
+same.row.pos2 <- same.row.pos2[ ! is.na(same.row.pos2)]
+any.id.row <- TRUE
+}
+if(is.null(same.row.pos1) & is.null(same.row.pos2)){
+any.id.row <- FALSE
+}else if(length(same.row.pos1) == 0L & length(same.row.pos2) == 0L){
+any.id.row <- FALSE
+}else if(all(same.row.pos1 == "TOO BIG FOR EVALUATION") & all(same.row.pos2 == "TOO BIG FOR EVALUATION")){
+any.id.row <- NULL
+}
+}else{
+any.id.row <- FALSE
+# same.row.pos1 and 2 remain NULL
+}
+if(same.row.nb == TRUE){ # because if not the same row nb, the col cannot be identical
+if(as.double(ncol(data1)) * ncol(data2) <= 1e10){ # comparison of data frame columns is much easier than rows because no need to use t() before converting to list for fast comparison. as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
+# if(all(sapply(data1, FUN = typeof) == "integer") & all(sapply(data2, FUN = typeof) == "integer") & as.double(ncol(data1)) * ncol(data2) <= 1e10){ # fast method for integers (thus not data frames). as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
+tempo1 <- c(data1)
+tempo2 <- c(data2)
+same.col.pos1 <- which(tempo1 %in% tempo2)
+same.col.pos2 <- which(tempo2 %in% tempo1)
+same.col.match1 <- match(tempo1, tempo2)
+same.col.match2 <- match(tempo2, tempo1)
+# }else if(as.double(ncol(data1)) * ncol(data2) <= 1e6){ # as.double(ncol(data1)) to prevent integer overflow because R is 32 bits for integers
+# same.col.pos1 <- logical(length = ncol(data1)) # FALSE by default
+# same.col.pos1[] <- FALSE # security
+# same.col.pos2 <- logical(length = ncol(data2)) # FALSE by default
+# same.col.pos2[] <- FALSE # security
+# same.col.match1 <- rep(NA, ncol(data1))
+# same.col.match2 <- rep(NA, ncol(data2))
+# for(i3 in 1:ncol(data1)){
+# for(i4 in 1:ncol(data2)){
+# if(identical(data1[ , i3], data2[ , i4])){
+# same.col.pos1[i3] <- TRUE
+# same.col.pos2[i4] <- TRUE
+# same.col.match1[i3] <- i4
+# same.col.match2[i4] <- i3
+# }
+# }
+# }
+# same.col.pos1 <- which(same.col.pos1)
+# same.col.pos2 <- which(same.col.pos2)
+}else{
+same.col.pos1 <- "TOO BIG FOR EVALUATION"
+same.col.pos2 <- "TOO BIG FOR EVALUATION"
+}
+names(same.col.pos1) <- NULL
+names(same.col.pos2) <- NULL
+if(all(is.na(same.col.pos1))){
+same.col.pos1 <- NULL
+}else{
+same.col.pos1 <- same.col.pos1[ ! is.na(same.col.pos1)]
+any.id.col <- TRUE
+}
+if(all(is.na(same.col.pos2))){
+same.col.pos2 <- NULL
+}else{
+same.col.pos2 <- same.col.pos2[ ! is.na(same.col.pos2)]
+any.id.col <- TRUE
+}
+if(is.null(same.col.pos1) & is.null(same.col.pos2)){
+any.id.col <- FALSE
+}else if(length(same.col.pos1) == 0L & length(same.col.pos2) == 0L){
+any.id.col <- FALSE
+}else if(all(same.col.pos1 == "TOO BIG FOR EVALUATION") & all(same.col.pos2 == "TOO BIG FOR EVALUATION")){
+any.id.col <- NULL
+}
+}else{
+any.id.col <- FALSE
+# same.col.pos1 and 2 remain NULL
+}
+if(same.dim == TRUE){
+names(data1) <- NULL
+row.names(data1) <- NULL
+names(data2) <- NULL
+row.names(data2) <- NULL
+if(identical(data1, data2)){
+identical.content <- TRUE
+}else{
+identical.content <- FALSE
+}
+}else{
+identical.content <- FALSE
+}
+}
+output <- list(same.class = same.class, class = class, same.dim = same.dim, dim = dim, same.row.nb = same.row.nb, row.nb = row.nb, same.col.nb = same.col.nb , col.nb = col.nb, same.row.name = same.row.name, row.name = row.name, any.id.row.name = any.id.row.name, same.row.names.pos1 = same.row.names.pos1, same.row.names.pos2 = same.row.names.pos2, same.row.names.match1 = same.row.names.match1, same.row.names.match2 = same.row.names.match2, common.row.names = common.row.names, same.col.name = same.col.name, col.name = col.name,any.id.col.name = any.id.col.name, same.col.names.pos1 = same.col.names.pos1, same.col.names.pos2 = same.col.names.pos2, same.col.names.match1 = same.col.names.match1, same.col.names.match2 = same.col.names.match2, common.col.names = common.col.names, any.id.row = any.id.row, same.row.pos1 = same.row.pos1, same.row.pos2 = same.row.pos2, same.row.match1 = same.row.match1, same.row.match2 = same.row.match2, any.id.col = any.id.col, same.col.pos1 = same.col.pos1, same.col.pos2 = same.col.pos2, same.col.match1 = same.col.match1, same.col.match2 = same.col.match2, identical.object = identical.object, identical.content = identical.content)
+return(output)
 }
 
 
-######## fun_codon_finder() #### gives the codon number and position in the codon of nucleotid positions
+######## fun_comp_list() #### comparison of two lists
 
 
-fun_codon_finder <- function(
-    pos, 
-    begin, 
-    end
-){
-    # AIM
-    # gives the codon number and position in the codon of nucleotid positions
-    # WARNINGS
-    # Only for coding sequences (no introns): ((end - begin) + 1) / 3 must be an integer (i.e., modulo zero)
-    # Negatives positions allowed but this implies that one base has the position 0 in the sequence
-    # ARGUMENTS
-    # pos: vector of integers indicating the positions of nucleotids in a sequence. Must be between begin and end arguments
-    # begin: single integer indicating the position of the first base of the coding sequence
-    # end: single indicating the position of the last base of the coding sequence
-    # RETURN
-    # a data frame with column names:
-    # pos: values of the pos argument
-    # codon_nb: the codon number in the CDS encompassing the pos value
-    # codon_pos: the position of pos in the codon (either 1, 2 or 3)
-    # codon_begin: the first base position of the codon
-    # codon_end: the last base position of the codon
-    # REQUIRED PACKAGES
-    # None
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # fun_check()
-    # EXAMPLE
-    # fun_codon_finder(c(5, 6, 8, 10), begin = 5, end = 10)
-    # fun_codon_finder(c(0, 5, 6, 8, 10), begin = -2, end = 12)
-    # see http
-    # DEBUGGING
-    # pos = c(5, 6, 8, 10) ; begin = 5 ; end = 10
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words
-    # end reserved words
-    # arg with no default values
-    mandat.args <- c(
-        "pos", 
-        "begin", 
-        "end"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = pos, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = begin, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = end, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){ # normally no NA
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "pos", 
-        "begin", 
-        "end"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    # end warning initiation
-    # other checkings
-    if(begin >= end){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": end ARGUMENT MUST BE STRICTLY GREATER THAN begin ARGUMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if((end - begin + 1) %% 3 != 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": ((end - begin) + 1) / 3 MUST BE AN INTEGER (I.E., MODULO ZERO)")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(pos < begin | pos > end)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": pos ARGUMENT VALUES MUST BE BETWEEN begin AND end ARGUMENT VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end other checkings
-    # reserved word checking
-    # end reserved word checking
-    # end second round of checking and data preparation
-    # package checking
-    # end package checking
-    # main code
-    first <- seq.int(from = begin, to = end, by = 3)
-    last <- seq.int(from = begin + 2, to = end, by = 3)
-    tempo <- lapply(X = pos, FUN = function(x = X){
-        tempo.log <- x >= first & x <= last
-        if(sum(tempo.log, na.rm = TRUE) != 1){ # check that 1 possible TRUE
-            tempo.cat <- paste0("ERROR IN ", function.name, ": INTERNAL ERROR. CODE HAS TO BE MODIFIED")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            codon_nb <- which(tempo.log)
-            codon_pos <- as.integer((x - (begin + (codon_nb - 1) * 3) + 1))
-            codon_begin <- as.integer(first[tempo.log])
-            codon_end <- as.integer(last[tempo.log])
-        }
-        return(data.frame(codon_nb = codon_nb, codon_pos = codon_pos, codon_begin = codon_begin, codon_end = codon_end))
-    })
-    tempo <- do.call("rbind", tempo)
-    output <- data.frame(pos = as.integer(pos), tempo)
-    return(output)
+fun_comp_list <- function(data1, data2){
+# AIM
+# compare two lists. Check and report in a list if the 2 datasets have:
+# same length
+# common names
+# common compartments
+# ARGUMENTS
+# data1: list
+# data2: list
+# RETURN
+# a list containing:
+# $same.length: logical. Are number of elements identical?
+# $length: number of elements in the 2 datasets (NULL otherwise)
+# $same.names: logical. Are element names identical ?
+# $name: name of elements of the 2 datasets if identical (NULL otherwise)
+# $any.id.name: logical. Is there any element names identical ?
+# $same.names.pos1: positions, in data1, of the element names identical in data2
+# $same.names.pos2: positions, in data2, of the compartment names identical in data1
+# $any.id.compartment: logical. is there any identical compartments ?
+# $same.compartment.pos1: positions, in data1, of the compartments identical in data2
+# $same.compartment.pos2: positions, in data2, of the compartments identical in data1
+# $identical.object: logical. Are objects identical (kind of object, compartment names and content)?
+# $identical.content: logical. Are content objects identical (identical compartments excluding compartment names)?
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# none
+# EXAMPLES
+# obs1 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; obs2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; fun_comp_list(obs1, obs2)
+# obs1 = list(1:5, LETTERS[1:2]) ; obs2 = list(a = 1:5, b = LETTERS[1:2]) ; fun_comp_list(obs1, obs2)
+# obs1 = list(b = 1:5, c = LETTERS[1:2]) ; obs2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; fun_comp_list(obs1, obs2)
+# obs1 = list(b = 1:5, c = LETTERS[1:2]) ; obs2 = list(LETTERS[5:9], matrix(1:6), 1:5) ; fun_comp_list(obs1, obs2)
+# DEBUGGING
+# data1 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) ; data2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) # for function debugging
+# data1 = list(a = 1:5, b = LETTERS[1:2]) ; data2 = list(a = 1:5, b = LETTERS[1:2], d = matrix(1:6)) # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# argument checking
+if( ! any(class(data1) %in% "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! any(class(data2) %in% "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) # activate this line and use the function to check arguments status
+# end argument checking
+# main code
+same.length <- NULL
+length <- NULL
+same.names <- NULL
+name <- NULL
+any.id.name <- NULL
+same.names.pos1 <- NULL
+same.names.pos2 <- NULL
+any.id.compartment <- NULL
+same.compartment.pos1 <- NULL
+same.compartment.pos2 <- NULL
+identical.object <- NULL
+identical.content <- NULL
+if(identical(data1, data2)){
+same.length <- TRUE
+length <- length(data1)
+if( ! is.null(names(data1))){
+same.names <- TRUE
+name <- names(data1)
+any.id.name <- TRUE
+same.names.pos1 <- 1:length(data1)
+same.names.pos2 <- 1:length(data2)
+}
+any.id.compartment <- TRUE
+same.compartment.pos1 <- 1:length(data1)
+same.compartment.pos2 <- 1:length(data2)
+identical.object <- TRUE
+identical.content <- TRUE
+}else{
+identical.object <- FALSE
+if( ! identical(length(data1), length(data2))){
+same.length<- FALSE
+}else{
+same.length<- TRUE
+length <- length(data1)
+}
+if( ! (is.null(names(data1)) & is.null(names(data2)))){
+if( ! identical(names(data1), names(data2))){
+same.names <- FALSE
+}else{
+same.names <- TRUE
+name <- names(data1)
+}
+any.id.name <- FALSE
+if(any(names(data1) %in% names(data2))){
+any.id.name <- TRUE
+same.names.pos1 <- which(names(data1) %in% names(data2))
+}
+if(any(names(data2) %in% names(data1))){
+any.id.name <- TRUE
+same.names.pos2 <- which(names(data2) %in% names(data1))
+}
+}
+names(data1) <- NULL
+names(data2) <- NULL
+any.id.compartment <- FALSE
+if(any(data1 %in% data2)){
+any.id.compartment <- TRUE
+same.compartment.pos1 <- which(data1 %in% data2)
+}
+if(any(data2 %in% data1)){
+any.id.compartment <- TRUE
+same.compartment.pos2 <- which(data2 %in% data1)
+}
+if(same.length == TRUE & ! all(is.null(same.compartment.pos1), is.null(same.compartment.pos2))){
+if(identical(same.compartment.pos1, same.compartment.pos2)){
+identical.content <- TRUE
+}else{
+identical.content <- FALSE
+}
+}else{
+identical.content <- FALSE
+}
+}
+output <- list(same.length = same.length, length = length, same.names = same.names, name = name, any.id.name = any.id.name, same.names.pos1 = same.names.pos1, same.names.pos2 = same.names.pos2, any.id.compartment = any.id.compartment, same.compartment.pos1 = same.compartment.pos1, same.compartment.pos2 = same.compartment.pos2, identical.object = identical.object, identical.content = identical.content)
+return(output)
 }
 
 
-################ Graphics management
-
-
-# this order can be used:
-# fun_width()
-# fun_open()
-# fun_prior_plot() # not for ggplot2
-# plot() or any other plotting
-# fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
-# fun_close()
-
+######## fun_test() #### test combinations of argument values of a function and return errors (and graphs)
 
-######## fun_width() #### window width depending on classes to plot
 
+# add traceback https://stackoverflow.com/questions/47414119/how-to-read-a-traceback-in-r
 
-fun_width <- function(
-    class.nb, 
-    inches.per.class.nb = 1, 
-    ini.window.width = 7, 
-    inch.left.space, 
-    inch.right.space, 
-    boundarie.space = 0.5
+fun_test <- function(
+fun, 
+arg, 
+val, 
+expect.error = NULL, 
+parall = FALSE, 
+thread.nb = NULL, 
+print.count = 10, 
+plot.fun = FALSE, 
+export = FALSE, 
+res.path = NULL, 
+lib.path = NULL, 
+cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
 ){
-    # AIM
-    # rescale the width of a window to open depending on the number of classes to plot
-    # can be used for height, considering that it is as if it was a width
-    # this order can be used:
-    # fun_width()
-    # fun_open()
-    # fun_prior_plot() # not for ggplot2
-    # plot() or any other plotting
-    # fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
-    # fun_close()
-    # ARGUMENTS
-    # class.nb: number of class to plot
-    # inches.per.class.nb: number of inches per unit of class.nb. 2 means 2 inches for each boxplot for instance
-    # ini.window.width:initial window width in inches
-    # inch.left.space: left horizontal margin of the figure region (in inches)
-    # inch.right.space: right horizontal margin of the figure region (in inches)
-    # boundarie.space: space between the right and left limits of the plotting region and the plot (0.5 means half a class width)
-    # RETURN
-    # the new window width in inches
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_width(class.nb = 10, inches.per.class.nb = 0.2, ini.window.width = 7, inch.left.space = 1, inch.right.space = 1, boundarie.space = 0.5)
-    # DEBUGGING
-    # class.nb = 10 ; inches.per.class.nb = 0.2 ; ini.window.width = 7 ; inch.left.space = 1 ; inch.right.space = 1 ; boundarie.space = 0.5 # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = class.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = inches.per.class.nb, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = ini.window.width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = inch.left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = inch.right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = boundarie.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    range.max <- class.nb + boundarie.space # the max range of the future plot
-    range.min <- boundarie.space # the min range of the future plot
-    window.width <- inch.left.space + inch.right.space + inches.per.class.nb * (range.max - range.min)
-    return(window.width)
+# AIM
+# test combinations of argument values of a function
+# WARNINGS
+# Limited to 43 arguments with at least 2 values each. The total number of arguments tested can be more if the additional arguments have a single value. The limit is due to nested "for" loops (https://stat.ethz.ch/pipermail/r-help/2008-March/157341.html), but it should not be a problem since the number of tests would be 2^43 > 8e12
+# ARGUMENTS
+# fun: character string indicating the name of the function tested (without brackets)
+# arg: vector of character strings of arguments of fun. At least arguments that do not have default values must be present in this vector
+# val: list with number of compartments equal to length of arg, each compartment containing values of the corresponding argument in arg. Each different value must be in a list or in a vector. For instance, argument 3 in arg is a logical argument (values accepted TRUE, FALSE, NA). Thus, compartment 3 of val can be either list(TRUE, FALSE, NA), or c(TRUE, FALSE, NA). NULL value alone must be written list(NULL)
+# expect.error: list of exactly the same structure as val argument, but containing FALSE or TRUE, depending on whether error is expected (TRUE) or not (FALSE) for each corresponding value of val. A message is returned depending on discrepancies between the expected and observed errors. BEWARE: not always possible to write the expected errors for all the combination of argument values. Ignored if NULL
+# parall: logical. Force parallelization ?
+# thread.nb: numeric value indicating the number of threads to use if ever parallelization is required. If NULL, all the available threads will be used. Ignored if parall is FALSE
+# print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
+# plot.fun: logical. Plot the plotting function tested for each test?
+# export: logical. Export the results into a .RData file and into a .txt file? If FALSE, return a list into the console (see below). BEWARE: will be automatically set to TRUE if parall is TRUE. This means that when using parallelization, the results are systematically exported, not returned into the console
+# res.path: character string indicating the absolute pathway of folder where the txt results and pdfs, containing all the plots, will be saved. Several txt and pdf, one per thread, if parallelization. Ignored if export is FALSE. Must be specified if parall is TRUE or if export is TRUE
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# cute.path: character string indicating the absolute path of the cute.R file. Will be remove when cute will be a package. Ignored if parall is FALSE
+# REQUIRED PACKAGES
+# lubridate
+# parallel if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
+# pdftools if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
+# If the tested function is in a package, this package must be imported first (no parallelization) or must be in the classical R package folder indicated by the lib.path argument (parallelization)
+# RETURN
+# if export is FALSE a list containing:
+# $fun: the tested function
+# $instruction: the initial instruction
+# $sys.info: system and packages info
+# $data: a data frame of all the combination tested, containing the following columns:
+# the different values tested, named by arguments
+# $kind: a vector of character strings indicating the kind of test result: either "ERROR", or "WARNING", or "OK"
+# $problem: a logical vector indicating if error or not
+# $expected.error: optional logical vector indicating the expected error specified in the expect.error argument
+# $message: either NULL if $kind is always "OK", or the messages
+# if export is TRUE 1) the same list object into a .RData file, 2) also the $data data frame into a .txt file, and 3) if expect.error is non NULL and if any discrepancy, the $data data frame into a .txt file but containing only the rows with discrepancies between expected and observed errors
+# one or several pdf if a plotting function is tested and if the plot.fun argument is TRUE
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_get_message()
+# fun_pack()
+# EXAMPLES
+# fun_test(fun = "unique", arg = c("x", "incomparables"), val = list(x = list(1:10, c(1,1,2,8), NA), incomparable = c(TRUE, FALSE, NA)))
+# fun_test(fun = "fun_round", arg = c("data", "dec.nb", "after.lead.zero"), val = list(L1 = list(c(1, 1.0002256, 1.23568), "a", NA), L2 = list(2, c(1,3), NA), L3 = c(TRUE, FALSE, NA)))
+# fun_test(fun = "plot", arg = c("x", "y"), val = list(x = list(1:10, 12:13, NA, (1:10)^2), y = list(1:10, NA, NA)),  expect.error = list(x = list(FALSE, TRUE, TRUE, FALSE), y = list(FALSE, TRUE, TRUE)), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = NULL)
+# fun_test(fun = "plot", arg = c("x", "y"), val = list(x = list(1:10, 12:13, NA, (1:10)^2), y = list(1:10, NA, NA)), parall = FALSE, thread.nb = 4, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\")
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_test(fun = "fun_gg_boxplot", arg = c("data1", "y", "categ"), val = list(L1 = list(L1 = obs1), L2 = list(L1 = "Time"), L3 = list(L1 = "Group1")))
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_test(fun = "fun_gg_boxplot", arg = c("data1", "y", "categ"), val = list(L1 = list(obs1), L2 = "Time", L3 = "Group1"), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\")
+# library(ggplot2) ; fun_test(fun = "geom_histogram", arg = c("data", "mapping"), val = list(x = list(data.frame(X = "a", stringsAsFactors = TRUE)), y = list(ggplot2::aes(x = X))), parall = FALSE, thread.nb = NULL, plot.fun = TRUE, res.path = "C:\\Users\\Gael\\Desktop\\", lib.path = "C:\\Program Files\\R\\R-4.0.2\\library\\") # BEWARE: ggplot2::geom_histogram does not work
+# DEBUGGING
+# fun = "unique" ; arg = "x" ; val = list(x = list(1:10, c(1,1,2,8), NA)) ; expect.error = list(x = list(FALSE, FALSE, TRUE)) ; parall = FALSE ; thread.nb = NULL ; plot.fun = FALSE ; export = FALSE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 1 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
+# fun = "unique" ; arg = c("x", "incomparables") ; val = list(x = list(1:10, c(1,1,2,8), NA), incomparable = c(TRUE, FALSE, NA)) ; expect.error = NULL ; parall = FALSE ; thread.nb = 2 ; plot.fun = FALSE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 10 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
+# fun = "plot" ; arg = c("x", "y") ; val = list(x = list(1:10, 12:13, NA), y = list(1:10, NA, NA)) ; expect.error = list(x = list(FALSE, FALSE, TRUE, FALSE), y = list(FALSE, TRUE, TRUE)) ; print.count = 10 ; parall = FALSE ; thread.nb = NULL ; plot.fun = TRUE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL # for function debugging
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun = "fun_gg_boxplot" ; arg = c("data1", "y", "categ") ; val = list(L1 = list(L1 = obs1), L2 = list(L1 = "Time"), L3 = list(L1 = "Group1")) ; expect.error = NULL ; print.count = 10 ; parall = FALSE ; thread.nb = NULL ; plot.fun = TRUE ; export = TRUE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL # for function debugging
+# fun = "unique" ; arg = "x" ; val = list(list(1:3, mean)) ; expect.error = list(TRUE, TRUE) ; parall = FALSE ; thread.nb = NULL ; plot.fun = FALSE ; export = FALSE ; res.path = "C:\\Users\\Gael\\Desktop\\" ; lib.path = NULL ; print.count = 1 ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R" # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check", 
+"fun_get_message", 
+"fun_pack"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
 }
-
-
-######## fun_open() #### open a GUI or pdf graphic window
-
-
-fun_open <- function(
-    pdf = TRUE, 
-    pdf.path = "working.dir", 
-    pdf.name = "graph", 
-    width = 7, 
-    height = 7, 
-    paper = "special", 
-    pdf.overwrite = FALSE, 
-    rescale = "fixed", 
-    remove.read.only = TRUE, 
-    return.output = FALSE
-){
-    # AIM
-    # open a pdf or screen (GUI) graphic window and return initial graphic parameters
-    # this order can be used:
-    # fun_width()
-    # fun_open()
-    # fun_prior_plot() # not for ggplot2
-    # plot() or any other plotting
-    # fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
-    # fun_close()
-    # WARNINGS
-    # On Linux, use pdf = TRUE, if (GUI) graphic window is not always available, meaning that X is not installed (clusters for instance). Use X11() in R to test if available
-    # ARGUMENTS:
-    # pdf: logical. Use pdf display? If FALSE, a GUI is opened
-    # pdf.path: where the pdf is saved (do not terminate by / or \\). Write "working.dir" if working directory is required (default). Ignored if pdf == FALSE
-    # pdf.name: name of the pdf file containing the graphs (the .pdf extension is added by the function, if not detected in the name end). Ignored if pdf == FALSE
-    # width: width of the window (in inches)
-    # height: height of the window (in inches)
-    # paper: paper argument of the pdf function (paper format). Only used for pdf(). Either "a4", "letter", "legal", "us", "executive", "a4r", "USr" or "special". If "special", means that the paper dimension will be width and height. With another paper format, if width or height is over the size of the paper, width or height will be modified such that the plot is adjusted to the paper dimension (see $dim in the returned list below to see the modified dimensions). Ignored if pdf == FALSE
-    # pdf.overwrite: logical. Existing pdf can be overwritten? . Ignored if pdf == FALSE
-    # rescale: kind of GUI. Either "R", "fit", or "fixed". Ignored on Mac and Linux OS. See ?windows for details
-    # remove.read.only: logical. remove the read only (R.O.) graphical parameters? If TRUE, the graphical parameters are returned without the R.O. parameters. The returned $ini.par list can be used to set the par() of a new graphical device. If FALSE, graphical parameters are returned with the R.O. parameters, which provides information like text dimension (see ?par() ). The returned $ini.par list can be used to set the par() of a new graphical device, but generate a warning message. Ignored if return.output == FALSE. 
-    # return.output: logical. Return output ? If TRUE the output list is displayed
-    # RETURN
-    # a list containing:
-    # $pdf.loc: path of the pdf created
-    # $ini.par: initial par() parameters
-    # $zone.ini: initial window spliting
-    # $dim: dimension of the graphical device (in inches)
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_open(pdf = FALSE, pdf.path = "C:/Users/Gael/Desktop", pdf.name = "graph", width = 7, height = 7, paper = "special", pdf.overwrite = FALSE, return.output = TRUE)
-    # DEBUGGING
-    # pdf = TRUE ; pdf.path = "C:/Users/Gael/Desktop" ; pdf.name = "graphs" ; width = 7 ; height = 7 ; paper = "special" ; pdf.overwrite = FALSE ; rescale = "fixed" ; remove.read.only = TRUE ; return.output = TRUE # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = pdf, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = pdf.path, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = pdf.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = height, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = paper, options = c("a4", "letter", "legal", "us", "executive", "a4r", "USr", "special", "A4", "LETTER", "LEGAL", "US"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data =pdf.overwrite, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = rescale, options = c("R", "fit", "fixed"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = remove.read.only, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.output, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if(pdf.path == "working.dir"){
-        pdf.path <- getwd()
-    }else{
-        if(grepl(x = pdf.path, pattern = ".+/$")){
-            pdf.path <- sub(x = pdf.path, pattern = "/$", replacement = "") # remove the last /
-        }else if(grepl(x = pdf.path, pattern = ".+[\\]$")){ # or ".+\\\\$" # cannot be ".+\$" because \$ does not exist contrary to \n
-            pdf.path <- sub(x = pdf.path, pattern = "[\\]$", replacement = "") # remove the last /
-        }
-        if(dir.exists(pdf.path) == FALSE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\npdf.path ARGUMENT DOES NOT CORRESPOND TO EXISTING DIRECTORY\n", pdf.path)
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # par.ini recovery
-    # cannot use pdf(file = NULL), because some small differences between pdf() and other devices. For instance, differences with windows() for par()$fin, par()$pin and par()$plt
-    if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
-        open.fail <- NULL
-        grDevices::windows()
-        ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-        invisible(dev.off()) # close the new window
-    }else if(Sys.info()["sysname"] == "Linux"){
-        if(pdf == TRUE){
-            tempo.code <- 0
-            while(file.exists(paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf")) == TRUE){
-                tempo.code <- tempo.code + 1
-            }
-            grDevices::pdf(width = width, height = height, file=paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf"), paper = paper)
-            ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-            invisible(dev.off()) # close the pdf window
-            file.remove(paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf")) # remove the pdf file
-        }else{
-            # test if X11 can be opened
-            if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nTHIS FUNCTION CANNOT BE USED ON LINUX IF A Rplots.pdf FILE ALREADY EXISTS HERE\n", getwd())
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                open.fail <- suppressWarnings(try(grDevices::X11(), silent = TRUE))[] # try to open a X11 window. If open.fail == NULL, no problem, meaning that the X11 window is opened. If open.fail != NULL, a pdf can be opened here paste0(getwd(), "/Rplots.pdf")
-                if(is.null(open.fail)){
-                    ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-                    invisible(dev.off()) # close the new window
-                }else if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
-                    file.remove(paste0(getwd(), "/Rplots.pdf")) # remove the pdf file
-                    tempo.cat <- ("ERROR IN fun_open()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM (X GRAPHIC INTERFACE HAS TO BE SET)\nTO OVERCOME THIS, PLEASE SET pdf ARGUMENT TO TRUE AND RERUN")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }
-            }
-        }
-    }else{
-        open.fail <- NULL
-        grDevices::quartz()
-        ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-        invisible(dev.off()) # close the new window
-    }
-    # end par.ini recovery 
-    zone.ini <- matrix(1, ncol=1) # to recover the initial parameters for next figure region when device region split into several figure regions
-    if(pdf == TRUE){
-        if(grepl(x = pdf.name, pattern = "\\.pdf$")){
-            pdf.name <- sub(x = pdf.name, pattern = "\\.pdf$", replacement = "") # remove the last .pdf
-        }
-        pdf.loc <- paste0(pdf.path, "/", pdf.name, ".pdf")
-        if(file.exists(pdf.loc) == TRUE & pdf.overwrite == FALSE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\npdf.loc FILE ALREADY EXISTS AND CANNOT BE OVERWRITTEN DUE TO pdf.overwrite ARGUMENT SET TO TRUE\n", pdf.loc)
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            grDevices::pdf(width = width, height = height, file=pdf.loc, paper = paper)
-        }
-    }else if(pdf == FALSE){
-        pdf.loc <- NULL
-        if(Sys.info()["sysname"] == "Windows"){ # .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
-            grDevices::windows(width = width, height = height, rescale = rescale)
-        }else if(Sys.info()["sysname"] == "Linux"){
-            if( ! is.null(open.fail)){
-                tempo.cat <- "ERROR IN fun_open()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM (X GRAPHIC INTERFACE HAS TO BE SET)\nTO OVERCOME THIS, PLEASE SET pdf ARGUMENT TO TRUE AND RERUN"
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                grDevices::X11(width = width, height = height)
-            }
-        }else{
-            grDevices::quartz(width = width, height = height)
-        }
-    }
-    if(return.output == TRUE){
-        output <- list(pdf.loc = pdf.loc, ini.par = ini.par, zone.ini = zone.ini, dim = dev.size())
-        return(output)
-    }
 }
-
-
-######## fun_prior_plot() #### set graph param before plotting (erase axes for instance)
-
-
-fun_prior_plot <- function(
-    param.reinitial = FALSE, 
-    xlog.scale = FALSE, 
-    ylog.scale = FALSE, 
-    remove.label = TRUE, 
-    remove.x.axis = TRUE, 
-    remove.y.axis = TRUE, 
-    std.x.range = TRUE, 
-    std.y.range = TRUE, 
-    down.space = 1, 
-    left.space = 1, 
-    up.space = 1, 
-    right.space = 1, 
-    orient = 1, 
-    dist.legend = 3.5, 
-    tick.length = 0.5, 
-    box.type = "n", 
-    amplif.label = 1, 
-    amplif.axis = 1, 
-    display.extend = FALSE, 
-    return.par = FALSE
-){
-    # AIM
-    # very convenient to erase the axes for post plot axis redrawing using fun_post_plot()
-    # reinitialize and set the graphic parameters before plotting
-    # CANNOT be used if no graphic device already opened
-    # ARGUMENTS
-    # param.reinitial: reinitialize graphic parameters before applying the new ones, as defined by the other arguments? Either TRUE or FALSE
-    # xlog.scale: Log scale for the x-axis? Either TRUE or FALSE. If TRUE, erases the x-axis, except legend, for further drawing by fun_post_plot()(xlog argument of par())
-    # ylog.scale: Log scale for the y-axis? Either TRUE or FALSE. If TRUE, erases the y-axis, except legend, for further drawing by fun_post_plot()(ylog argument of par())
-    # remove.label: remove labels (axis legend) of the two axes? Either TRUE or FALSE (ann argument of par())
-    # remove.x.axis: remove x-axis except legend? Either TRUE or FALSE (control the xaxt argument of par()). Automately set to TRUE if xlog.scale == TRUE
-    # remove.y.axis: remove y-axis except legend? Either TRUE or FALSE (control the yaxt argument of par()). Automately set to TRUE if ylog.scale == TRUE
-    # std.x.range: standard range on the x-axis? TRUE (no range extend) or FALSE (4% range extend). Controls xaxs argument of par() (TRUE is xaxs = "i", FALSE is xaxs = "r")
-    # std.y.range: standard range on the y-axis? TRUE (no range extend) or FALSE (4% range extend). Controls yaxs argument of par() (TRUE is yaxs = "i", FALSE is yaxs = "r")
-    # down.space: lower vertical margin (in inches, mai argument of par())
-    # left.space: left horizontal margin (in inches, mai argument of par())
-    # up.space: upper vertical margin between plot region and grapical window (in inches, mai argument of par())
-    # right.space: right horizontal margin (in inches, mai argument of par())
-    # orient: scale number orientation (las argument of par()). 0, always parallel to the axis; 1, always horizontal; 2, always perpendicular to the axis; 3, always vertical
-    # dist.legend: numeric value that moves axis legends away in inches (first number of mgp argument of par() but in inches thus / 0.2)
-    # tick.length: length of the ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc. 0 means no tick
-    # box.type: bty argument of par(). Either "o", "l", "7", "c", "u", "]", the resulting box resembles the corresponding upper case letter. A value of "n" suppresses the box
-    # amplif.label: increase or decrease the size of the text in legends
-    # amplif.axis: increase or decrease the size of the scale numbers in axis
-    # display.extend: extend display beyond plotting region? Either TRUE or FALSE (xpd argument of par() without NA)
-    # return.par: return graphic parameter modification?
-    # RETURN
-    # return graphic parameter modification
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_prior_plot(param.reinitial = FALSE, xlog.scale = FALSE, ylog.scale = FALSE, remove.label = TRUE, remove.x.axis = TRUE, remove.y.axis = TRUE, std.x.range = TRUE, std.y.range = TRUE, down.space = 1, left.space = 1, up.space = 1, right.space = 1, orient = 1, dist.legend = 4.5, tick.length = 0.5, box.type = "n", amplif.label = 1, amplif.axis = 1, display.extend = FALSE, return.par = FALSE)
-    # DEBUGGING
-    # param.reinitial = FALSE ; xlog.scale = FALSE ; ylog.scale = FALSE ; remove.label = TRUE ; remove.x.axis = TRUE ; remove.y.axis = TRUE ; std.x.range = TRUE ; std.y.range = TRUE ; down.space = 1 ; left.space = 1 ; up.space = 1 ; right.space = 1 ; orient = 1 ; dist.legend = 4.5 ; tick.length = 0.5 ; box.type = "n" ; amplif.label = 1 ; amplif.axis = 1 ; display.extend = FALSE ; return.par = FALSE # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = param.reinitial, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = xlog.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = ylog.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = remove.label, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = remove.x.axis, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = remove.y.axis, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = std.x.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = std.y.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = down.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = up.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = orient, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.type, options = c("o", "l", "7", "c", "u", "]", "n"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = amplif.label, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = amplif.axis, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = display.extend, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.par, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if(is.null(dev.list())){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THIS FUNCTION CANNOT BE USED IF NO GRAPHIC DEVICE ALREADY OPENED (dev.list() IS CURRENTLY NULL)")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # par.ini recovery
-    # cannot use pdf(file = NULL), because some small differences between pdf() and other devices. For instance, differences with windows() for par()$fin, par()$pin and par()$plt
-    if(param.reinitial == TRUE){
-        if( ! all(names(dev.cur()) == "null device")){
-            active.wind.nb <- dev.cur()
-        }else{
-            active.wind.nb <- 0
-        }
-        if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
-            grDevices::windows()
-            ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-            invisible(dev.off()) # close the new window
-        }else if(Sys.info()["sysname"] == "Linux"){
-            if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": THIS FUNCTION CANNOT BE USED ON LINUX WITH param.reinitial SET TO TRUE IF A Rplots.pdf FILE ALREADY EXISTS HERE: ", getwd())
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                open.fail <- suppressWarnings(try(grDevices::X11(), silent = TRUE))[] # try to open a X11 window. If open.fail == NULL, no problem, meaning that the X11 window is opened. If open.fail != NULL, a pdf can be opened here paste0(getwd(), "/Rplots.pdf")
-                if(is.null(open.fail)){
-                    ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-                    invisible(dev.off()) # close the new window
-                }else if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
-                    ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-                    invisible(dev.off()) # close the new window
-                    file.remove(paste0(getwd(), "/Rplots.pdf")) # remove the pdf file
-                }else{
-                    tempo.cat <- ("ERROR IN fun_prior_plot()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM (X GRAPHIC INTERFACE HAS TO BE SET)\nTO OVERCOME THIS, PLEASE USE PDF GRAPHIC INTERFACES AND RERUN")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }
-            }
-        }else{ # macOS
-            grDevices::quartz()
-            ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened)
-            invisible(dev.off()) # close the new window
-        }
-        if( ! all(names(dev.cur()) == "null device")){
-            invisible(dev.set(active.wind.nb)) # go back to the active window if exists
-            par(ini.par) # apply the initial par to current window
-        }
-    }
-    # end par.ini recovery
-    if(remove.x.axis == TRUE){
-        par(xaxt = "n") # suppress the y-axis label
-    }else{
-        par(xaxt = "s")
-    }
-    if(remove.y.axis == TRUE){
-        par(yaxt = "n") # suppress the y-axis label
-    }else{
-        par(yaxt = "s")
-    }
-    if(std.x.range == TRUE){
-        par(xaxs = "i")
-    }else{
-        par(xaxs = "r")
-    }
-    if(std.y.range == TRUE){
-        par(yaxs = "i")
-    }else{
-        par(yaxs = "r")
-    }
-    par(mai = c(down.space, left.space, up.space, right.space), ann = ! remove.label, las = orient, mgp = c(dist.legend/0.2, 1, 0), xpd = display.extend, bty= box.type, cex.lab = amplif.label, cex.axis = amplif.axis)
-    par(tcl = -par()$mgp[2] * tick.length) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
-    if(xlog.scale == TRUE){
-        par(xaxt = "n", xlog = TRUE) # suppress the x-axis label
-    }else{
-        par(xlog = FALSE)
-    }
-    if(ylog.scale == TRUE){
-        par(yaxt = "n", ylog = TRUE) # suppress the y-axis label
-    }else{
-        par(ylog = FALSE)
-    }
-    if(return.par == TRUE){
-        tempo.par <- par()
-        return(tempo.par)
-    }
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words
+# end reserved words
+# arg with no default values
+mandat.args <- c(
+"fun", 
+"arg", 
+"val"
+)
+tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), "))")))
+print(tempo)
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = fun, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = arg, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = val, class = "list", fun.name = function.name) ; eval(ee)
+if( ! is.null(expect.error)){
+tempo <- fun_check(data = expect.error, class = "list", fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = parall, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(parall == TRUE){
+if( ! is.null(thread.nb)){
+tempo <- fun_check(data = thread.nb, typeof = "integer", double.as.integer.allowed = TRUE, neg.values = FALSE, length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & thread.nb < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": thread.nb PARAMETER MUST EQUAL OR GREATER THAN 1: ", thread.nb)
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = plot.fun, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = export, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(res.path)){
+tempo <- fun_check(data = res.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = cute.path, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# new environment
+env.name <- paste0("env", as.numeric(Sys.time()))
+if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
+}
+# end new environment
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"fun", 
+"arg", 
+"val", 
+# "expect.erro", # because can be NULL
+"parall", 
+# "thread.nb", # because can be NULL
+"print.count", 
+"plot.fun", 
+"export", 
+# "res.path", # because can be NULL
+# "lib.path", # because can be NULL
+"cute.path"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+# end warning initiation
+# other checkings
+if(grepl(x = fun, pattern = "()$")){ # remove ()
+fun <- sub(x = fun, pattern = "()$", replacement = "")
+}
+if( ! exists(fun)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CHARACTER STRING IN fun ARGUMENT DOES NOT EXIST IN THE R WORKING ENVIRONMENT: ", paste(fun, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}else if( ! all(base::class(get(fun)) == "function")){ # here no env = sys.nframe(), inherit = FALSE for get() because fun is a function in the classical scope
+tempo.cat <- paste0("ERROR IN ", function.name, ": fun ARGUMENT IS NOT CLASS \"function\" BUT: ", paste(base::class(get(fun)), collapse = "\n"), "\nCHECK IF ANY CREATED OBJECT WOULD HAVE THE NAME OF THE TESTED FUNCTION")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(tempo$problem == FALSE & base::length(arg) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": arg ARGUMENT CANNOT BE LENGTH 0")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+for(i2 in 1:base::length(val)){
+tempo1 <- fun_check(data = val[[i2]], class = "vector", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = val[[i2]], class = "list", na.contain = TRUE, fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": COMPARTMENT ", i2, " OF val ARGUMENT MUST BE A VECTOR OR A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}else if(tempo1$problem == FALSE){ # vector split into list compartments
+val[[i2]] <- split(x = val[[i2]], f = 1:base::length(val[[i2]]))
+}
+}
+if(base::length(arg) != base::length(val)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF arg ARGUMENT MUST BE IDENTICAL TO LENGTH OF val ARGUMENT:\nHERE IT IS: ", base::length(arg), " VERSUS ", base::length(val))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+args <- names(formals(get(fun))) # here no env = sys.nframe(), inherit = FALSE for get() because fun is a function in the classical scope
+if( ! all(arg %in% args)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": SOME OF THE STRINGS IN arg ARE NOT ARGUMENTS OF fun\nfun ARGUMENTS: ", paste(args, collapse = " "),"\nPROBLEMATIC STRINGS IN arg: ", paste(arg[ ! arg %in% args], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(sum(sapply(val, FUN = length) > 1) > 43){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CANNOT TEST MORE THAN 43 ARGUMENTS IF THEY ALL HAVE AT LEAST 2 VALUES EACH\nHERE THE NUMBER IS: ", sum(sapply(val, FUN = length) > 1))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if( ! is.null(expect.error)){
+if(base::length(val) != base::length(expect.error)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF val ARGUMENT MUST BE IDENTICAL TO LENGTH OF expect.error ARGUMENT:\nHERE IT IS: ", base::length(val), " VERSUS ", base::length(expect.error))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+for(i3 in 1:base::length(expect.error)){
+tempo1 <- fun_check(data = expect.error[[i3]], class = "vector",  mode = "logical", fun.name = function.name)
+tempo2 <- fun_check(data =  expect.error[[i3]], class = "list", fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": COMPARTMENT ", i3, " OF expect.error ARGUMENT MUST BE TRUE OR FALSE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}else if(tempo1$problem == FALSE){ # vector split into list compartments
+expect.error[[i3]] <- split(x = expect.error[[i3]], f = 1:base::length(expect.error[[i3]]))
+}
+}
+}
+if( ! is.null(res.path)){
+if( ! all(dir.exists(res.path))){ # separation to avoid the problem of tempo$problem == FALSE and res.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE res.path ARGUMENT DOES NOT EXISTS:\n", paste(res.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+}
+if(parall == TRUE & is.null(res.path)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": res.path ARGUMENT MUST BE SPECIFIED IF parall ARGUMENT IS TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(is.null(res.path) & export == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": res.path ARGUMENT MUST BE SPECIFIED IF export ARGUMENT TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(parall == TRUE & export == FALSE){
+export <- TRUE
+tempo.cat <- paste0("WARNING FROM ", function.name, ": export ARGUMENT CONVERTED TO TRUE BECAUSE thread.nb ARGUMENT IS NOT NULL")
+warning(paste0("\n", tempo.cat, "\n"), call. = FALSE)
+}
+if( ! is.null(lib.path)){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+}
+if(parall == TRUE){
+if(grepl(x = cute.path, pattern = "^http")){
+tempo.error1 <- any(grepl(x = fun_get_message(data = "source(cute.path)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE)), pattern = "^[Ee]rror"))
+tempo.error2 <- FALSE
+}else{
+tempo.error1 <- FALSE
+tempo.error2 <- ! file.exists(cute.path)
+}
+if(tempo.error1 | tempo.error2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(grepl(x = cute.path, pattern = "^http"), "URL", "FILE"), " PATH INDICATED IN THE cute.path PARAMETER DOES NOT EXISTS:\n", cute.path)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+}
+# end other checkings
+# reserved word checking
+# end reserved word checking
+# end second round of checking and data preparation
+# package checking
+fun_pack(req.package = c("lubridate"), lib.path = lib.path)
+if(parall == TRUE){
+fun_pack(req.package = c("parallel", "pdftools"), lib.path = lib.path)
+}
+# end package checking
+# declaration of special plot functions
+sp.plot.fun <- c("fun_gg_scatter", "fun_gg_bar", "fun_gg_boxplot")
+# end declaration of special plot functions
+# main code
+ini.warning.length <- base::options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+cat("\nfun_test JOB IGNITION\n")
+ini.date <- Sys.time()
+ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
+if(export == TRUE){
+res.path <- paste0(res.path, "/fun_test_res_", trunc(ini.time))
+if(dir.exists(res.path)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": FOLDER ALREADY EXISTS\n", res.path, "\nPLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+dir.create(res.path)
+}
+}
+total.comp.nb <- prod(sapply(val, FUN = "length"))
+cat(paste0("\nTHE TOTAL NUMBER OF TESTS IS: ", total.comp.nb, "\n"))
+# creation of the txt instruction that includes several loops
+loop.string <- NULL
+end.loop.string <- NULL
+fun.args <- NULL
+fun.args2 <- NULL
+error.values <- NULL
+arg.values <- "list("
+for(i1 in 1:base::length(arg)){
+if(parall == FALSE){
+if(base::length(val[[i1]]) > 1){ # loop only if more than one value in base::length(val[[i1]])
+loop.string <- paste0(loop.string, "for(i", i1, " in 1:", base::length(val[[i1]]), "){")
+end.loop.string <- paste0(end.loop.string, "}")
+}
+}else{
+loop.string <- "for(i in x){"
+end.loop.string <- "}"
+}
+fun.args <- paste0(
+fun.args, 
+ifelse(i1 == 1L, "", ", "), 
+arg[i1], 
+" = val[[", 
+i1, 
+"]][[", 
+if(parall == FALSE){
+if(base::length(val[[i1]]) > 1){
+paste0("i", i1)
+}else{
+"1" # a unique element in val[[i1]]
+}
+}else{
+paste0("i.list[[", i1, "]][i]")
+}, 
+"]]"
+)
+fun.args2 <- paste0(
+fun.args2, 
+ifelse(i1 == 1L, "", ", "), 
+arg[i1], 
+" = val[[", 
+i1, 
+"]][[', ", 
+if(parall == FALSE){
+if(base::length(val[[i1]]) > 1){
+paste0("i", i1)
+}else{
+"1" # a unique element in val[[i1]]
+}
+}else{
+paste0("i.list[[", i1, "]][i]")
+}, 
+", ']]"
+)
+arg.values <- paste0(
+arg.values, 
+"val[[", i1, "]][[", 
+if(parall == FALSE){
+if(base::length(val[[i1]]) > 1){
+paste0("i", i1)
+}else{
+"1" # a unique element in val[[i1]]
+}
+}else{
+paste0("i.list[[", i1, "]][i]")
+}, 
+"]]", 
+ifelse(i1 == base::length(arg), "", ", ")
+)
+error.values <- paste0(
+error.values, 
+ifelse(i1 == 1L, "", " | "), 
+"expect.error[[", i1, "]][[", 
+if(parall == FALSE){
+if(base::length(expect.error[[i1]]) > 1){
+paste0("i", i1)
+}else{
+"1" # a unique element in expect.error[[i1]]
+}
+}else{
+paste0("i.list[[", i1, "]][i]")
+}, 
+"]]"
+)
+}
+arg.values <- paste0(arg.values, ")")
+fun.test <- paste0(fun, "(", fun.args, ")")
+fun.test2 <- paste0("paste0('", fun, "(", fun.args2, ")')")
+# plot title for special plot functions
+if(plot.fun == TRUE){
+plot.kind <- "classic"
+if(fun %in% sp.plot.fun){
+plot.kind <- "special"
+if(any(arg %in% "title")){ # this is for the special functions
+tempo.match <- regmatches(x = fun.test, m = regexpr(text = fun.test, pattern = "title = .+[,)]"))
+tempo.match <- substring(tempo.match , 1, nchar(tempo.match) - 1)
+fun.test <- sub(x = fun.test, pattern = tempo.match, replacement = paste0(tempo.match, "\ntempo.title"))
+}else{
+fun.test <- sub(x = fun.test, pattern = ")$", replacement = ", title = tempo.title)")
+}
+}
+}
+# end plot title for special plot functions
+kind <- character()
+problem <- logical()
+expected.error <- logical()
+res <- character()
+count <- 0
+print.count.loop <- 0
+plot.count <- 0
+if(base::length(arg) == 1L){
+data <- data.frame()
+}else{ # base::length(arg) == 0L already tested above
+data <- data.frame(t(vector("character", base::length(arg))), stringsAsFactors = FALSE)[-1, ] # -1 to remove the single row created and to have an empty data frame with base::length(arg) columns
+}
+code <- paste(
+loop.string, '
+count <- count + 1
+print.count.loop <- print.count.loop + 1
+arg.values.print <- eval(parse(text = arg.values)) # recover the list of the i1 compartment
+for(j3 in 1:base::length(arg.values.print)){ # WARNING: do not use i1, i2 etc., here because already in loop.string
+tempo.capt <- capture.output(tempo.error <- fun_get_message(data =  paste0("paste(arg.values.print[[", j3, "]])"), kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))) # collapsing arg.values sometimes does not work (with function for instance)
+if( ! is.null(tempo.error)){
+arg.values.print[[j3]] <- paste0("SPECIAL VALUE OF CLASS ", base::class(arg.values.print[[j3]]), " AND TYPE ", base::typeof(arg.values.print[[j3]]))
+}
+}
+data <- rbind(data, as.character(sapply(arg.values.print, FUN = "paste", collapse = " ")), stringsAsFactors = FALSE) # each colum is a test
+tempo.capt <- capture.output(tempo.try.error <- fun_get_message(data = eval(parse(text = fun.test2)), kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE))) # data argument needs a character string but eval(parse(text = fun.test2)) provides it (eval parse replace the i1, i2, etc., by the correct values, meaning that only val is required in the env.name environment)
+tempo.capt <- capture.output(tempo.try.warning <- fun_get_message(data = eval(parse(text = fun.test2)), kind = "warning", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE), print.no = TRUE)) # data argument needs a character string but eval(parse(text = fun.test2)) provides it (eval parse replace the i1, i2, etc., by the correct values, meaning that only val is required in the env.name environment)
+if( ! is.null(expect.error)){
+expected.error <- c(expected.error, eval(parse(text = error.values)))
+}
+if( ! is.null(tempo.try.error)){
+kind <- c(kind, "ERROR")
+problem <- c(problem, TRUE)
+res <- c(res, tempo.try.error)
+}else{
+if( ! is.null(tempo.try.warning)){
+kind <- c(kind, "WARNING")
+problem <- c(problem, FALSE)
+res <- c(res, tempo.try.warning)
+}else{
+kind <- c(kind, "OK")
+problem <- c(problem, FALSE)
+res <- c(res, "")
+}
+if(plot.fun == TRUE){
+invisible(dev.set(window.nb))
+plot.count <- plot.count + 1
+tempo.title <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), ifelse(parall == FALSE, count, x[count])))
+if(plot.kind == "classic"){
+eval(parse(text = fun.test))
+tempo <- fun_post_plot(corner.text = tempo.title)
+}else if(plot.kind == "special"){
+eval(parse(text = fun.test))
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR 1 IN ", function.name, ": CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}
+if(print.count.loop == print.count){
+print.count.loop <- 0
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+final.loop <- (tempo.time - ini.time) / count * ifelse(parall == FALSE, total.comp.nb, base::length(x)) # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
+final.exp <- as.POSIXct(final.loop, origin = ini.date)
+cat(paste0(ifelse(parall == FALSE, "\n", paste0("\nIN PROCESS ", process.id, " | ")), "LOOP ", format(count, big.mark=","), " / ", format(ifelse(parall == FALSE, total.comp.nb, base::length(x)), big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+}
+if(count == ifelse(parall == FALSE, total.comp.nb, base::length(x))){
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+cat(paste0(ifelse(parall == FALSE, "\nLOOP PROCESS ENDED | ", paste0("\nPROCESS ", process.id, " ENDED | ")), "LOOP ", format(count, big.mark=","), " / ", format(ifelse(parall == FALSE, total.comp.nb, base::length(x)), big.mark=","), " | TIME SPENT: ", tempo.lapse, "\n\n"))
+}
+', 
+end.loop.string
+)
+# end creation of the txt instruction that includes several loops
+if(parall == TRUE){
+# list of i numbers that will be split
+i.list <- vector("list", base::length(val)) # positions to split in parallel jobs
+for(i2 in 1:base::length(arg)){
+if(i2 == 1L){
+tempo.divisor <- total.comp.nb / base::length(val[[i2]])
+i.list[[i2]] <- rep(1:base::length(val[[i2]]), each = as.integer(tempo.divisor))
+tempo.multi <- base::length(val[[i2]])
+}else{
+tempo.divisor <- tempo.divisor / base::length(val[[i2]])
+i.list[[i2]] <- rep(rep(1:base::length(val[[i2]]), each = as.integer(tempo.divisor)), time = as.integer(tempo.multi))
+tempo.multi <- tempo.multi * base::length(val[[i2]])
+}
+}
+# end list of i numbers that will be split
+tempo.cat <- paste0("PARALLELIZATION INITIATED AT: ", ini.date)
+cat(paste0("\n", tempo.cat, "\n"))
+tempo.thread.nb = parallel::detectCores(all.tests = FALSE, logical = TRUE) # detect the number of threads
+if(tempo.thread.nb < thread.nb){
+thread.nb <- tempo.thread.nb
+}
+tempo.cat <- paste0("NUMBER OF THREADS USED: ", thread.nb)
+cat(paste0("\n    ", tempo.cat, "\n"))
+Clust <- parallel::makeCluster(thread.nb, outfile = paste0(res.path, "/fun_test_parall_log.txt")) # outfile to print or cat during parallelization (only possible in a file, outfile = "" do not work on windows)
+tempo.cat <- paste0("SPLIT OF TEST NUMBERS IN PARALLELISATION:")
+cat(paste0("\n    ", tempo.cat, "\n"))
+cluster.list <- parallel::clusterSplit(Clust, 1:total.comp.nb) # split according to the number of cluster
+str(cluster.list) # using print(str()) add a NULL below the result
+cat("\n")
+paral.output.list <- parallel::clusterApply( # paral.output.list is a list made of thread.nb compartments, each made of n / thread.nb (mat theo column number) compartment. Each compartment receive the corresponding results of fun_permut(), i.e., data (permuted mat1.perm), warning message, cor (final correlation) and count (number of permutations)
+cl = Clust,
+x = cluster.list,
+function.name = function.name, 
+instruction = instruction, 
+thread.nb = thread.nb, 
+print.count = print.count, 
+total.comp.nb = total.comp.nb, 
+sp.plot.fun = sp.plot.fun,
+i.list = i.list, 
+fun.tested = fun,
+arg.values = arg.values,
+fun.test = fun.test,
+fun.test2 = fun.test2,
+kind = kind,
+problem = problem,
+res = res,
+count = count,
+plot.count = plot.count,
+data = data,
+code = code,
+plot.fun = plot.fun, 
+res.path = res.path, 
+lib.path = lib.path, 
+cute.path = cute.path, 
+fun = function(
+x, 
+function.name, 
+instruction, 
+thread.nb, 
+print.count, 
+total.comp.nb, 
+sp.plot.fun, 
+i.list, 
+fun.tested, 
+arg.values, 
+fun.test, 
+fun.test2, 
+kind, 
+problem, 
+res, 
+count, 
+plot.count, 
+data, 
+code, 
+plot.fun, 
+res.path, 
+lib.path, 
+cute.path
+){
+# check again: very important because another R
+process.id <- Sys.getpid()
+cat(paste0("\nPROCESS ID ", process.id, " -> TESTS ", x[1], " TO ", x[base::length(x)], "\n"))
+source(cute.path, local = .GlobalEnv)
+fun_pack(req.package = "lubridate", lib.path = lib.path, load = TRUE) # load = TRUE to be sure that functions are present in the environment. And this prevent to use R.lib.path argument of fun_python_pack()
+# end check again: very important because another R
+# plot management
+if(plot.fun == TRUE){
+pdf(file = paste0(res.path, "/plots_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".pdf", paste0("-", x[base::length(x)], ".pdf"))))
+}else{
+pdf(file = NULL) # send plots into a NULL file, no pdf file created
+}
+window.nb <- dev.cur()
+invisible(dev.set(window.nb))
+# end plot management
+# new environment
+ini.date <- Sys.time()
+ini.time <- as.numeric(ini.date) # time of process begin, converted into 
+env.name <- paste0("env", ini.time)
+if(exists(env.name, where = -1)){ # verify if still ok when fun_test() is inside a function
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("val", val, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # var replaced by val
+}
+# end new environment
+print.count.loop <- 0
+suppressMessages(suppressWarnings(eval(parse(text = code))))
+colnames(data) <- arg
+if( ! is.null(expect.error)){
+data <- data.frame(data, kind = kind, problem = problem, expected.error = expected.error, message = res, stringsAsFactors = FALSE)
+}else{
+data <- data.frame(data, kind = kind, problem = problem, message = res, stringsAsFactors = FALSE)
+}
+row.names(data) <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), x))
+sys.info <- sessionInfo()
+sys.info$loadedOnly <- sys.info$loadedOnly[order(names(sys.info$loadedOnly))] # sort the packages
+invisible(dev.off(window.nb))
+rm(env.name) # optional, because should disappear at the end of the function execution
+# output
+output <- list(fun = fun, instruction = instruction, sys.info = sys.info) # data = data finally removed from the output list, because everything combined in a RData file at the end
+save(output, file = paste0(res.path, "/fun_test_", x[1], ifelse(base::length(x) == 1L, ".RData", paste0("-", x[base::length(x)], ".RData"))))
+if(plot.fun == TRUE & plot.count == 0L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN PROCESS ", process.id, ": NO PDF PLOT BECAUSE ONLY ERRORS REPORTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+file.remove(paste0(res.path, "/plots_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".pdf", paste0("-", x[base::length(x)], ".pdf"))))
+}
+table.out <- as.matrix(data)
+# table.out[table.out == ""] <- " " # does not work # because otherwise read.table() converts "" into NA
+table.out <- gsub(table.out, pattern = "\n", replacement = " ")
+write.table(table.out, file = paste0(res.path, "/table_from_fun_test_", x[1], ifelse(base::length(x) == 1L, ".txt", paste0("-", x[base::length(x)], ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
+}
+)
+parallel::stopCluster(Clust)
+# files assembly
+if(base::length(cluster.list) > 1){
+for(i2 in 1:base::length(cluster.list)){
+tempo.file <- paste0(res.path, "/table_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".txt", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".txt"))) # txt file
+tempo <- read.table(file = tempo.file, header = TRUE, stringsAsFactors = FALSE, sep = "\t", row.names = 1, comment.char = "", colClasses = "character") #  row.names = 1 (1st column) because now read.table() adds a NA in the header if the header starts by a tabulation, comment.char = "" because colors with #, colClasses = "character" otherwise convert "" (from NULL) into NA
+if(file.exists(paste0(res.path, "/plots_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".pdf", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".pdf"))))){
+tempo.pdf <- paste0(res.path, "/plots_from_fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".pdf", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".pdf"))) # pdf file
+}else{
+tempo.pdf <- NULL
+}
+tempo.rdata <- paste0(res.path, "/fun_test_", min(cluster.list[[i2]], na.rm = TRUE), ifelse(base::length(cluster.list[[i2]]) == 1L, ".RData", paste0("-", max(cluster.list[[i2]], na.rm = TRUE), ".RData"))) # RData file
+if(i2 == 1L){
+final.file <- tempo
+final.pdf <- tempo.pdf
+# new env for RData combining
+env.name <- paste0("env", ini.time)
+if(exists(env.name, where = -1)){ # verify if still ok when fun_test() is inside a function
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+# end new env for RData combining
+}else{
+assign(env.name, new.env())
+load(tempo.rdata, envir = get(env.name))
+tempo.rdata1 <- tempo.rdata
+assign("final.output", get("output", envir = get(env.name)), envir = get(env.name))
+}
+}else{
+final.file <- rbind(final.file, tempo, stringsAsFactors = TRUE)
+final.pdf <- c(final.pdf, tempo.pdf)
+load(tempo.rdata, envir = get(env.name))
+if( ! identical(get("final.output", envir = get(env.name))[c("R.version", "locale", "platform")], get("output", envir = get(env.name))[c("R.version", "locale", "platform")])){
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIFFERENCE BETWEEN OUTPUTS WHILE THEY SHOULD BE IDENTICAL\nPLEASE CHECK\n", tempo.rdata1, "\n", tempo.rdata)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+# add the differences in RData $sysinfo into final.output
+tempo.base1 <- sort(get("final.output", envir = get(env.name))$sys.info$basePkgs)
+tempo.base2 <- sort(get("output", envir = get(env.name))$sys.info$basePkgs)
+tempo.other1 <- names(get("final.output", envir = get(env.name))$sys.info$otherPkgs)
+tempo.other2 <- names(get("output", envir = get(env.name))$sys.info$otherPkgs)
+tempo.loaded1 <- names(get("final.output", envir = get(env.name))$sys.info$loadedOnly)
+tempo.loaded2 <- names(get("output", envir = get(env.name))$sys.info$loadedOnly)
+assign("final.output", {
+x <- get("final.output", envir = get(env.name))
+y <- get("output", envir = get(env.name))
+x$sys.info$basePkgs <- sort(unique(tempo.base1, tempo.base2))
+if( ! all(tempo.other2 %in% tempo.other1)){
+x$sys.info$otherPkgs <- c(x$sys.info$otherPkgs, y$sys.info$otherPkgs[ ! (tempo.other2 %in% tempo.other1)])
+x$sys.info$otherPkgs <- x$sys.info$otherPkgs[order(names(x$sys.info$otherPkgs))]
+}
+if( ! all(tempo.loaded2 %in% tempo.loaded1)){
+x$sys.info$loadedOnly <- c(x$sys.info$loadedOnly, y$sys.info$loadedOnly[ ! (tempo.loaded2 %in% tempo.loaded1)])
+x$sys.info$loadedOnly <- x$sys.info$loadedOnly[order(names(x$sys.info$loadedOnly))]
+}
+x
+}, envir = get(env.name))
+# add the differences in RData $sysinfo into final.output
+}
+}
+file.remove(c(tempo.file, tempo.rdata))
+}
+# combine pdf and save
+if( ! is.null(final.pdf)){
+pdftools::pdf_combine(
+input = final.pdf,
+output = paste0(res.path, "/plots_from_fun_test_1-", total.comp.nb, ".pdf")
+)
+file.remove(final.pdf)
+}
+# end combine pdf and save
+# save RData
+assign("output", c(get("final.output", envir = get(env.name)), data = list(final.file)), envir = get(env.name))
+save(output, file = paste0(res.path, "/fun_test__1-", total.comp.nb, ".RData"), envir = get(env.name))
+rm(env.name) # optional, because should disappear at the end of the function execution
+# end save RData
+# save txt
+write.table(final.file, file = paste0(res.path, "/table_from_fun_test_1-", total.comp.nb, ".txt"), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
+# end save txt
+if( ! is.null(expect.error)){
+final.file <- final.file[ ! final.file$problem == final.file$expected.error, ]
+if(nrow(final.file) == 0L){
+cat(paste0("NO DISCREPANCY BETWEEN EXPECTED AND OBSERVED ERRORS\n\n"))
+}else{
+cat(paste0("DISCREPANCIES BETWEEN EXPECTED AND OBSERVED ERRORS (SEE THE discrepancy_table_from_fun_test_1-", total.comp.nb, ".txt FILE)\n\n"))
+write.table(final.file, file = paste0(res.path, "/discrepancy_table_from_fun_test_1-", total.comp.nb, ".txt"), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
+}
+}
+}
+# end files assembly
+}else{
+# plot management
+if(plot.fun == TRUE){
+pdf(file = paste0(res.path, "/plots_from_fun_test_1", ifelse(total.comp.nb == 1L, ".pdf", paste0("-", total.comp.nb, ".pdf"))))
+}else{
+pdf(file = NULL) # send plots into a NULL file, no pdf file created
+}
+window.nb <- dev.cur()
+invisible(dev.set(window.nb))
+# end plot management
+# new environment
+env.name <- paste0("env", ini.time)
+if(exists(env.name, where = -1)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("val", val, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # var replaced by val
+}
+# end new environment
+suppressMessages(suppressWarnings(eval(parse(text = code))))
+colnames(data) <- arg
+expect.data <- data.frame()
+if( ! is.null(expect.error)){
+data <- data.frame(data, kind = kind, problem = problem, expected.error = expected.error, message = res, stringsAsFactors = FALSE)
+}else{
+data <- data.frame(data, kind = kind, problem = problem, message = res, stringsAsFactors = FALSE)
+}
+row.names(data) <- paste0("test_", sprintf(paste0("%0", nchar(total.comp.nb), "d"), 1:total.comp.nb))
+sys.info <- sessionInfo()
+sys.info$loadedOnly <- sys.info$loadedOnly[order(names(sys.info$loadedOnly))] # sort the packages
+invisible(dev.off(window.nb))
+rm(env.name) # optional, because should disappear at the end of the function execution
+# output
+output <- list(fun = fun, instruction = instruction, sys.info = sys.info, data = data)
+if(plot.fun == TRUE & plot.count == 0L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO PDF PLOT BECAUSE ONLY ERRORS REPORTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+file.remove(paste0(res.path, "/plots_from_fun_test_1", ifelse(total.comp.nb == 1L, ".pdf", paste0("-", total.comp.nb, ".pdf"))))
+}
+if( ! is.null(expect.error)){
+expect.data <- output$data[ ! output$data$problem == output$data$expected.error, ]
+if(nrow(expect.data) == 0L){
+cat(paste0("NO DISCREPANCY BETWEEN EXPECTED AND OBSERVED ERRORS\n\n"))
+}else{
+cat(paste0("DISCREPANCIES BETWEEN EXPECTED AND OBSERVED ERRORS (SEE THE ", if(export == TRUE){paste0("discrepancy_table_from_fun_test_1", ifelse(total.comp.nb == 1L, "", paste0("-", total.comp.nb)), ".txt FILE")}else{"$data RESULT"}, ")\n\n"))
+if(export == TRUE){
+expect.data <- as.matrix(expect.data)
+expect.data <- gsub(expect.data, pattern = "\n", replacement = "  ")
+write.table(expect.data, file = paste0(res.path, "/discrepancy_table_from_fun_test_1", ifelse(total.comp.nb == 1L, ".txt", paste0("-", total.comp.nb, ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
+}
+}
+}
+if( ! is.null(warn)){
+base::options(warning.length = 8170)
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = base::options(warning.length = ini.warning.length), add = TRUE)
+if(export == TRUE){
+save(output, file = paste0(res.path, "/fun_test_1", ifelse(total.comp.nb == 1L, ".RData", paste0("-", total.comp.nb, ".RData"))))
+table.out <- as.matrix(output$data)
+table.out <- gsub(table.out, pattern = "\n", replacement = "  ")
+write.table(table.out, file = paste0(res.path, "/table_from_fun_test_1", ifelse(total.comp.nb == 1L, ".txt", paste0("-", total.comp.nb, ".txt"))), row.names = TRUE, col.names = NA, append = FALSE, quote = FALSE, sep = "\t", eol = "\n", na = "")
+}else{
+return(output)
+}
+}
+# after return() ?
+end.date <- Sys.time()
+end.time <- as.numeric(end.date)
+total.lapse <- round(lubridate::seconds_to_period(end.time - ini.time))
+cat(paste0("fun_test JOB END\n\nTIME: ", end.date, "\n\nTOTAL TIME LAPSE: ", total.lapse, "\n\n\n"))
+}
+
+
+################ Object modification
+
+
+######## fun_name_change() #### check a vector of character strings and modify any string if present in another vector
+
+
+fun_name_change <- function(data1, data2, added.string = "_modif"){
+# AIM
+# this function allow to check if a vector of character strings, like column names of a data frame, has elements present in another vector (vector of reserved words or column names of another data frame before merging)
+# ARGUMENTS
+# data1: vector of character strings to check and modify
+# data2: reference vector of character strings
+# added.string: string added at the end of the modified string in data1 if present in data2
+# RETURN
+# a list containing
+# $data: the modified data1 (in the same order as in the initial data1)
+# $ini: the initial elements before modification. NULL if no modification
+# $post: the modified elements in the same order as in ini. NULL if no modification
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# obs1 <- c("A", "B", "C", "D") ; obs2 <- c("A", "C") ; fun_name_change(obs1, obs2)
+# obs1 <- c("A", "B", "C", "C_modif1", "D") ; obs2 <- c("A", "A_modif1", "C") ; fun_name_change(obs1, obs2) # the function checks that the new names are neither in obs1 nor in obs2 (increment the number after the added string)
+# DEBUGGING
+# data1 = c("A", "B", "C", "D") ; data2 <- c("A", "C") ; added.string = "_modif" # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data1, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = data2, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = added.string, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+ini <- NULL
+post <- NULL
+if(any(data1 %in% data2)){
+tempo.names <- data1[data1 %in% data2]
+ini <- NULL
+post <- NULL
+for(i2 in 1:length(tempo.names)){
+count <- 0
+tempo <- tempo.names[i2]
+while(any(tempo %in% data2) | any(tempo %in% data1)){
+count <- count + 1
+tempo <- paste0(tempo.names[i2], "_modif", count)
+}
+data1[data1 %in% tempo.names[i2]] <- paste0(tempo.names[i2], "_modif", count)
+if(count != 0){
+ini <- c(ini, tempo.names[i2])
+post <- c(post, paste0(tempo.names[i2], "_modif", count))
+}
+}
+data <- data1
+}else{
+data <- data1
+}
+output <- list(data = data, ini = ini, post = post)
+return(output)
+}
+
+
+######## fun_df_remod() #### remodeling a data frame to have column name as a qualitative values and vice-versa
+
+
+fun_df_remod <- function(
+data, 
+quanti.col.name = "quanti", 
+quali.col.name = "quali"
+){
+# AIM
+# if the data frame is made of n numeric columns, a new data frame is created, with the 1st column gathering all the numeric values, and the 2nd column being the name of the columns of the initial data frame. If row names were present in the initial data frame, then a new ini_rowname column is added with the names of the rows
+
+ 
+# If the data frame is made of one numeric column and one character or factor column, a new data frame is created, with the new columns corresponding to the split numeric values (according to the character column). NA are added a the end of each column to have the same number of rows. BEWARE: in such data frame, rows are not individuals. This means that in the example below, values 10 and 20 are associated on the same row but that means nothing in term of association
+
+ 
+
+# ARGUMENTS
+# data: data frame to convert
+# quanti.col.name: optional name for the quanti column of the new data frame
+# quali.col.name: optional name for the quali column of the new data frame
+# RETURN
+# the modified data frame
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# obs <- data.frame(col1 = (1:4)*10, col2 = c("A", "B", "A", "A"), stringsAsFactors = TRUE) ; obs ; fun_df_remod(obs)
+# obs <- data.frame(col1 = (1:4)*10, col2 = 5:8, stringsAsFactors = TRUE) ; obs ; fun_df_remod(obs, quanti.col.name = "quanti", quali.col.name = "quali")
+# obs <- data.frame(col1 = (1:4)*10, col2 = 5:8, stringsAsFactors = TRUE) ; rownames(obs) <- paste0("row", 1:4) ; obs ; fun_df_remod(obs, quanti.col.name = "quanti", quali.col.name = "quali")
+# DEBUGGING
+# data = data.frame(a = 1:3, b = 4:6, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
+# data = data.frame(a = 1:3, b = 4:6, c = 11:13, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
+# data = data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
+# data = data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = TRUE) ; quanti.col.name = "TEST" ; quali.col.name = "quali" # for function debugging
+# data = data.frame(b = letters[1:3], a = 1:3, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
+# data = data.frame(b = c("e", "e", "h"), a = 1:3, stringsAsFactors = TRUE) ; quanti.col.name = "quanti" ; quali.col.name = "quali" # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking without fun_check()
+if( ! any(class(data) %in% "data.frame")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data ARGUMENT MUST BE A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking without fun_check()
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = quanti.col.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = quali.col.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+tempo.factor <- unlist(lapply(data, class))
+for(i in 1:length(tempo.factor)){ # convert factor columns as character
+if(all(tempo.factor[i] == "factor")){
+data[, i] <- as.character(data[, i])
+}
+}
+tempo.factor <- unlist(lapply(data, mode))
+if(length(data) == 2L){
+if( ! ((base::mode(data[, 1]) == "character" & base::mode(data[, 2]) == "numeric") | base::mode(data[, 2]) == "character" & base::mode(data[, 1]) == "numeric" | base::mode(data[, 2]) == "numeric" & base::mode(data[, 1]) == "numeric") ){
+tempo.cat <- paste0("ERROR IN ", function.name, ": IF data ARGUMENT IS A DATA FRAME MADE OF 2 COLUMNS, EITHER A COLUMN MUST BE NUMERIC AND THE OTHER CHARACTER, OR THE TWO COLUMNS MUST BE NUMERIC")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if((base::mode(data[, 1]) == "character" | base::mode(data[, 2]) == "character") & (quanti.col.name != "quanti" | quali.col.name != "quali")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": IMPROPER quanti.col.name OR quali.col.name RESETTINGS. THESE ARGUMENTS ARE RESERVED FOR DATA FRAMES MADE OF n NUMERIC COLUMNS ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+if( ! all(tempo.factor %in% "numeric")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": IF data ARGUMENT IS A DATA FRAME MADE OF ONE COLUMN, OR MORE THAN 2 COLUMNS, THESE COLUMNS MUST BE NUMERIC")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(( ! any(tempo.factor %in% "character")) & is.null(names(data))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": NUMERIC DATA FRAME in the data ARGUMENT MUST HAVE COLUMN NAMES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(all(tempo.factor %in% "numeric")){ # transfo 1
+quanti <- NULL
+for(i in 1:length(data)){
+quanti <-c(quanti, data[, i])
+}
+quali <- rep(names(data), each = nrow(data))
+output.data <- data.frame(quanti, quali, stringsAsFactors = TRUE, check.names = FALSE)
+names(output.data) <- c(quanti.col.name, quali.col.name)
+# add the ini_rowname column
+ini.rownames <- rownames(data)
+tempo.data <- data
+rownames(tempo.data) <- NULL
+null.rownames <- (tempo.data)
+if( ! identical(ini.rownames, null.rownames)){
+ini_rowname <- rep(ini.rownames, times = ncol(data))
+output.data <- cbind(output.data, ini_rowname, stringsAsFactors = TRUE)
+}
+}else{ # transfo 2
+if(class(data[, 1]) == "character"){
+data <- cbind(data[2], data[1], stringsAsFactors = TRUE)
+}
+nc.max <- max(table(data[, 2])) # effectif maximum des classes
+nb.na <- nc.max - table(data[,2]) # nombre de NA à ajouter pour réaliser la data frame
+tempo<-split(data[, 1], data[, 2])
+for(i in 1:length(tempo)){tempo[[i]] <- append(tempo[[i]], rep(NA, nb.na[i]))} # des NA doivent être ajoutés lorsque les effectifs sont différents entre les classes. C'est uniquement pour que chaque colonne ait le même nombre de lignes
+output.data<-data.frame(tempo, stringsAsFactors = TRUE, check.names = FALSE)
+}
+return(output.data)
+}
+
+
+
+
+######## fun_round() #### rounding number if decimal present
+
+
+fun_round <- function(data, dec.nb = 2, after.lead.zero = TRUE){
+# AIM
+# round a vector of values, if decimal, with the desired number of decimal digits after the decimal leading zeros
+# WARNINGS
+# Work well with numbers as character strings, but not always with numerical numbers because of the floating point
+# Numeric values are really truncated from a part of their decimal digits, whatever options(digits) settings
+# See ?.Machine or https://stackoverflow.com/questions/5173692/how-to-return-number-of-decimal-places-in-r, with the interexting formula: abs(x - round(x)) > .Machine$double.eps^0.5
+# ARGUMENTS
+# data: a vector of numbers (numeric or character mode)
+# dec.nb: number of required decimal digits
+# after.lead.zero: logical. If FALSE, rounding is performed for all the decimal numbers, whatever the leading zeros (e.g., 0.123 -> 0.12 and 0.00128 -> 0.00). If TRUE, dec.nb are taken after the leading zeros (e.g., 0.123 -> 0.12 and 0.00128 -> 0.0013)
+# RETURN
+# the modified vector
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, 10, 100.001, 333.0001254, 12312.1235), dec.nb = 2, after.lead.zero = FALSE), "\n\n") ; options(digits = ini.options)
+# ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, 10, 100.001, 333.0001254, 12312.1235), dec.nb = 2, after.lead.zero = TRUE), "\n\n") ; options(digits = ini.options)
+# ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, "10", "100.001", "333.0001254", "12312.1235"), dec.nb = 2, after.lead.zero = FALSE), "\n\n") ; options(digits = ini.options)
+# ini.options <- options()$digits ; options(digits = 8) ; cat(fun_round(data = c(NA, "10", "100.001", "333.0001254", "12312.1235"), dec.nb = 2, after.lead.zero = TRUE), "\n\n") ; options(digits = ini.options)
+# DEBUGGING
+# data = data = c(10, 100.001, 333.0001254, 12312.1235) ; dec.nb = 2 ; after.lead.zero = FALSE # # for function debugging
+# data = data = c("10", "100.001", "333.0001254", "12312.1235") ; dec.nb = 2 ; after.lead.zero = TRUE # # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking without fun_check()
+if( ! (all(typeof(data) == "character") | all(typeof(data) == "double") | all(typeof(data) == "integer"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A VECTOR OF NUMBERS (IN NUMERIC OR CHARACTER MODE)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking without fun_check()
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data, class = "vector", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dec.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = after.lead.zero, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+tempo <- grepl(x = data, pattern = "\\.") # detection of decimal numbers
+ini.mode <- base::mode(data)
+data <- as.character(data) # to really truncate decimal digits
+for(i in 1:length(data)){ # scan all the numbers of the vector
+if(tempo[i] == TRUE){ # means decimal number
+if(after.lead.zero == TRUE){
+zero.pos <- unlist(gregexpr(text=data[i], pattern = 0)) # recover all the position of the zeros in the number. -1 if no zeros (do not record the leading and trailing zeros)
+}else{
+zero.pos <- -1 # -1 as if no zero
+}
+dot.pos <- unlist(gregexpr(text=data[i], pattern = "\\.")) # recover all the position of the zeros in the number
+digit.pos <- unlist(gregexpr(text=data[i], pattern = "[[:digit:]]")) # recover all the position of the digits in the number
+dec.pos <- digit.pos[digit.pos > dot.pos]
+count <- 0
+while((dot.pos + count + 1) %in% zero.pos & (dot.pos + count + 1) <= max(dec.pos) & (count + dec.nb) < length(dec.pos)){ # count the number of leading zeros in the decimal part
+count <- count + 1
+}
+data[i] <- formatC(as.numeric(data[i]), digits = (count + dec.nb), format = "f")
+}
+}
+if(ini.mode != "character"){
+data <- as.numeric(data)
+}
+return(data)
+}
+
+
+######## fun_mat_rotate() #### 90° clockwise matrix rotation
+
+
+fun_mat_rotate <- function(data){
+# AIM
+# 90° clockwise matrix rotation
+# applied twice, the function provide the mirror matrix, according to vertical and horizontal symmetry
+# ARGUMENTS
+# data: matrix (matrix class)
+# RETURN
+# the modified matrix
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# obs <- matrix(1:10, ncol = 1) ; obs ; fun_mat_rotate(obs)
+# obs <- matrix(LETTERS[1:10], ncol = 5) ; obs ; fun_mat_rotate(obs)
+# DEBUGGING
+# data = matrix(1:10, ncol = 1)
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data, class = "matrix", fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+for (i in 1:ncol(data)){data[,i] <- rev(data[,i])}
+data <- t(data)
+return(data)
+}
+
+
+######## fun_mat_num2color() #### convert a numeric matrix into hexadecimal color matrix
+
+
+fun_mat_num2color <- function(
+mat1, 
+mat.hsv.h = TRUE, 
+notch = 1, 
+s = 1, 
+v = 1, 
+forced.color = NULL
+){
+# AIM
+# convert a matrix made of numbers into a hexadecimal matrix for rgb colorization
+# ARGUMENTS:
+# mat1: matrix 1 of non negative numerical values that has to be colored (matrix class). NA allowed
+# mat.hsv.h: logical. Is mat1 the h of hsv colors ? (if TRUE, mat1 must be between zero and 1). If FALSE, mat1 must be made of positive integer values without 0
+# notch: single value between 0 and 1 to shift the successive colors on the hsv circle by + notch
+# s: s argument of hsv(). Must be between 0 and 1
+# v: v argument of hsv(). Must be between 0 and 1
+# forced.color: Must be NULL or hexadecimal color code or name given by colors(). The first minimal values of mat1 will be these colors. All the color of mat1 can be forced using this argument
+# RETURN
+# a list containing:
+# $mat1.name: name of mat1
+# $colored.mat: colors of mat1 in hexa
+# $problem: logical. Is any colors of forced.color overlap the colors designed by the function. NULL if forced.color = NULL
+# $text.problem: text when overlapping colors. NULL if forced.color = NULL or problem == FALSE
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# mat1 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; dimnames(mat1) <- list(LETTERS[1:4], letters[1:2]) ; fun_mat_num2color(mat1, mat.hsv.h = FALSE, notch = 1, s = 1, v = 1, forced.color = NULL)
+# DEBUGGING
+# mat1 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; dimnames(mat1) <- list(LETTERS[1:4], letters[1:2]); mat.hsv.h = FALSE ; notch = 1 ; s = 1 ; v = 1 ; forced.color = c(hsv(1,1,1), hsv(0,0,0)) # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = mat1, mode = "numeric", class = "matrix", na.contain = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = mat.hsv.h, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = notch, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = s, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = v, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# argument checking without fun_check()
+if(mat.hsv.h == TRUE & fun_check(data = mat1, mode = "numeric", prop = TRUE)$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 ARGUMENT MUST BE A MATRIX OF PROPORTIONS SINCE THE mat.hsv.h ARGUMENT IS SET TO TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(forced.color)){
+tempo <- fun_check(data = forced.color, class = "character")
+if(any(tempo$problem == TRUE)){
+paste0("\n\n================\n\n", paste(tempo$text[tempo$problem], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! all(forced.color %in% colors() | grepl(pattern = "^#", forced.color))){ # check that all strings of forced.color start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": forced.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end argument checking without fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+problem <- NULL
+text.problem <- NULL
+mat1.name <- deparse(substitute(mat1))
+# change the scale of the plotted matrix
+if(mat.hsv.h == TRUE){
+if(any(min(mat1, na.rm = TRUE) < 0 | max(mat1, na.rm = TRUE) > 1, na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 MUST BE MADE OF VALUES BETWEEN 0 AND 1 BECAUSE mat.hsv.h ARGUMENT SET TO TRUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+if(any(mat1 - floor(mat1) > 0, na.rm = TRUE) | any(mat1 == 0L, na.rm = TRUE)){ # no need of isTRUE(all.equal()) because we do not require approx here but strictly 0, thus == is ok
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat1 MUST BE MADE OF INTEGER VALUES WITHOUT 0 BECAUSE mat.hsv.h ARGUMENT SET TO FALSE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+mat1 <- mat1 / max(mat1, na.rm = TRUE)
+}
+}
+if(notch != 1){
+different.color <- unique(as.vector(mat1))
+different.color <- different.color[ ! is.na(different.color)]
+tempo.different.color <- different.color + c(0, cumsum(rep(notch, length(different.color) - 1)))
+tempo.different.color <- tempo.different.color - floor(tempo.different.color)
+if(any(duplicated(tempo.different.color) == TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": DUPLICATED VALUES AFTER USING notch (", paste(tempo.different.color[duplicated(tempo.different.color)], collapse = " "), "). TRY ANOTHER notch VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(length(different.color) != length(tempo.different.color)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": LENGTH OF different.color (", paste(different.color, collapse = " "), ") DIFFERENT FROM LENGTH OF tempo.different.color (", paste(tempo.different.color, collapse = " "), ")")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+for(i in 1:length(different.color)){
+mat1[mat1 == different.color[i]] <- tempo.different.color[i] # no need of isTRUE(all.equal()) because different.color comes from mat1
+}
+}
+}
+if( ! is.null(forced.color)){
+hexa.values.to.change <- hsv(unique(sort(mat1))[1:length(forced.color)], s, v)
+}
+mat1[ ! is.na(mat1)] <- hsv(mat1[ ! is.na(mat1)], s, v)
+if( ! is.null(forced.color)){
+if(any(forced.color %in% mat1, na.rm = TRUE)){
+problem <- TRUE
+text.problem <- paste0("THE FOLLOWING COLORS WHERE INTRODUCED USING forced.color BUT WHERE ALREADY PRESENT IN THE COLORED MATRIX :", paste(forced.color[forced.color %in% mat1], collapse = " "))
+}else{
+problem <- FALSE
+}
+for(i in 1:length(hexa.values.to.change)){
+if( ! any(mat1 == hexa.values.to.change[i], na.rm = TRUE)){# no need of isTRUE(all.equal()) because character
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE ", hexa.values.to.change[i], " VALUE FROM hexa.values.to.change IS NOT REPRESENTED IN mat1 : ", paste(unique(as.vector(mat1)), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+mat1[which(mat1 == hexa.values.to.change[i])] <- forced.color[i] # no need of isTRUE(all.equal()) because character
+}
+}
+}
+output <- list(mat1.name = mat1.name, colored.mat = mat1, problem = problem, text.problem = text.problem)
+return(output)
+}
+
+
+######## fun_mat_op() #### assemble several matrices with operation
+
+
+fun_mat_op <- function(mat.list, kind.of.operation = "+"){
+# AIM
+# assemble several matrices of same dimensions by performing by case operation. For instance add the value of all the case 1 (row1 & column1) of the matrices and put it in the case 1 of a new matrix M, add the value of all the case 2 (row2 & column1) of the matrices and put it in the case 2 of a new matrix M, etc.
+ 
+# c: case
+# i: row number
+# j: column number
+# k: matrix number
+# z: number of matrices
+# ARGUMENTS:
+# mat.list: list of matrices
+# kind.of.operation: either "+" (by case addition), "-" (by case subtraction) or "*" (by case multiplication)
+# RETURN
+# the assembled matrix, with row and/or column names only if all the matrices have identical row/column names
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_comp_2d()
+# EXAMPLES
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "+")
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "*")
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], c(NA, NA))) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2), kind.of.operation = "-")
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(c("A1", "A2", "A3", "A4"), letters[1:2])) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat3 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; fun_mat_op(mat.list = list(mat1, mat2, mat3), kind.of.operation = "+")
+# DEBUGGING
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2) ; mat.list = list(mat1, mat2) ; kind.of.operation = "+" # for function debugging
+# mat1 = matrix(c(1,1,1,2,1,5,9,8), ncol = 2, dimnames = list(LETTERS[1:4], c(NA, NA))) ; mat2 = matrix(c(1,1,1,2,1,5,9,NA), ncol = 2, dimnames = list(LETTERS[1:4], letters[1:2])) ; mat.list = list(mat1, mat2) ; kind.of.operation = "*" # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_comp_2d() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = mat.list, class = "list", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = kind.of.operation, options = c("+", "-", "*"), length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# argument checking without fun_check()
+if(length(mat.list) < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat.list ARGUMENT MUST BE A LIST CONTAINING AT LEAST 2 MATRICES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+for(i1 in 1:length(mat.list)){
+tempo <- fun_check(data = mat.list[[i1]], class = "matrix", mode = "numeric", na.contain = TRUE)
+if(tempo$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ELEMENT ", i1, " OF mat.list ARGUMENT MUST BE A NUMERIC MATRIX")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+ident.row.names <- TRUE
+ident.col.names <- TRUE
+for(i1 in 2:length(mat.list)){
+tempo <- fun_comp_2d(data1 = mat.list[[1]], data2 = mat.list[[i1]])
+if(tempo$same.dim == FALSE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX ", i1, " OF mat.list ARGUMENT MUST HAVE THE SAME DIMENSION (", paste(dim(mat.list[[i1]]), collapse = " "), ") THAN THE MATRIX 1 IN mat.list (", paste(dim(mat.list[[1]]), collapse = " "), ")")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(tempo$same.row.name)){
+if(tempo$same.row.name != TRUE){ # != TRUE to deal with NA
+ident.row.names <- FALSE
+}
+}
+if( ! is.null(tempo$same.col.name)){
+if(tempo$same.col.name != TRUE){ # != TRUE to deal with NA
+ident.col.names <- FALSE
+}
+}
+}
+# end argument checking without fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+output <- mat.list[[1]]
+for(i1 in 2:length(mat.list)){
+output <- get(kind.of.operation)(output, mat.list[[i1]]) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+dimnames(output) <- NULL
+if(ident.row.names == TRUE){
+rownames(output) <- rownames(mat.list[[1]])
+}
+if(ident.col.names == TRUE){
+colnames(output) <- colnames(mat.list[[1]])
+}
+return(output)
+}
+
+
+######## fun_mat_inv() #### return the inverse of a square matrix
+
+
+fun_mat_inv <- function(mat){
+# AIM
+# return the inverse of a square matrix when solve() cannot
+# ARGUMENTS:
+# mat: a square numeric matrix without NULL, NA, Inf or single case (dimension 1, 1) of 0
+# RETURN
+# the inversed matrix
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# mat1 = matrix(c(1,1,1,2,1,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1) # use solve()
+# mat1 = matrix(c(0,0,0,0,0,0,0,0,0), ncol = 3) ; fun_mat_inv(mat = mat1) # use the trick
+# mat1 = matrix(c(1,1,1,2,Inf,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1)
+# mat1 = matrix(c(1,1,1,2,NA,5,9,8,9), ncol = 3) ; fun_mat_inv(mat = mat1)
+# mat1 = matrix(c(1,2), ncol = 1) ; fun_mat_inv(mat = mat1)
+# mat1 = matrix(0, ncol = 1) ; fun_mat_inv(mat = mat1)
+# mat1 = matrix(2, ncol = 1) ; fun_mat_inv(mat = mat1)
+# DEBUGGING
+# mat = matrix(c(1,1,1,2,1,5,9,8,9), ncol = 3) # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = mat, class = "matrix", mode = "numeric", fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# argument checking without fun_check()
+if(ncol(mat) != nrow(mat)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A SQUARE MATRIX")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(mat %in% c(Inf, -Inf, NA))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A MATRIX WITHOUT Inf, -Inf OR NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(all(mat == 0L) & ncol(mat) == 1L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT CANNOT BE A SQUARE MATRIX MADE OF A SINGLE CASE OF 0")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking without fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if(any(grepl(x = try(solve(mat), silent = TRUE)[], pattern = "[Ee]rror"))){
+tempo <- svd(mat)
+val.critique <- which(tempo$d < 10^-8)
+Diag.mod <- diag(1 / tempo$d)
+for(i in val.critique){
+Diag.mod[i, i] <- 0
+}
+return(tempo$v %*% Diag.mod %*% t(tempo$u))
+}else{
+return(solve(mat))
+}
+}
+
+
+######## fun_mat_fill() #### fill the empty half part of a symmetric square matrix
+
+
+fun_mat_fill <- function(mat, empty.cell.string = 0, warn.print = FALSE){
+# AIM
+# detect the empty half part of a symmetric square matrix (either topleft, topright, bottomleft or bottomright)
+# fill this empty half part using the other symmetric half part of the matrix
+# WARNINGS
+# a plot verification using fun_gg_heatmap() is recommanded
+# ARGUMENTS:
+# mat: a numeric or character square matrix with the half part (according to the grand diagonal) filled with NA (any kind of matrix), "0" (character matrix) or 0 (numeric matrix) exclusively (not a mix of 0 and NA in the empty part)
+# empty.cell.string: a numeric, character or NA (no quotes) indicating what empty cells are filled with
+# warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
+# RETURN
+# a list containing:
+# $mat: the filled matrix
+# $warn: the warning messages. Use cat() for proper display. NULL if no warning
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# mat1 = matrix(c(1,NA,NA,NA, 0,2,NA,NA, NA,3,4,NA, 5,6,7,8), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = NA, warn.print = TRUE) # bottomleft example
+# mat1 = matrix(c(1,1,1,2, 0,2,3,0, NA,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = NA, warn.print = TRUE) # error example
+# mat1 = matrix(c(1,1,1,2, 0,2,3,0, NA,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # bottomright example
+# mat1 = matrix(c(1,1,1,2, "a",2,3,NA, "a","a",0,0, "a","a","a",0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = "a", warn.print = TRUE) # topright example
+# mat1 = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # topleft example
+# mat1 = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,0, 5,0,0,0), ncol = 4) ; mat1 ; fun_mat_fill(mat = mat1, empty.cell.string = 0, warn.print = TRUE) # error example
+# DEBUGGING
+# mat = matrix(c(1,NA,NA,NA, 0,2,NA,NA, NA,3,4,NA, 5,6,7,8), ncol = 4) ; empty.cell.string = NA ; warn.print = TRUE # for function debugging
+# mat = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; empty.cell.string = 0 ; warn.print = TRUE # for function debugging # topleft example
+# mat = matrix(c(0,0,0,2, 0,0,3,0, 0,3,0,NA, 5,0,0,0), ncol = 4) ; empty.cell.string = NA ; warn.print = TRUE # for function debugging # topleft example
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = mat, class = "matrix", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = empty.cell.string, class = "vector", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# argument checking without fun_check()
+if(ncol(mat) != nrow(mat)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A SQUARE MATRIX")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (base::mode(mat) %in% c("numeric", "character"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MUST BE A NUMERIC OR CHARACTER MATRIX")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(nrow(mat) == 1L & ncol(mat) == 1L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT CANNOT BE A SQUARE MATRIX MADE OF A SINGLE CASE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(ifelse(is.na(empty.cell.string), ! any(is.na(mat)), ! any(mat == empty.cell.string, na.rm = TRUE))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": mat ARGUMENT MATRIX MUST HAVE CELLS WITH THE EMPTY STRING SPECIFIED IN empty.cell.string ARGUMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking without fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+list.diag <- vector("list", length = nrow(mat) - 1) 
+for(i1 in 1:(nrow(mat) - 1)){
+list.diag[[i1]] <- numeric(length = nrow(mat) - i1) # list made of zero
+}
+sector <- c("topleft", "topright", "bottomright", "bottomleft")
+diag.scan <-c( # same order as sector. Recover each diag from center to corner
+"mat[as.matrix(as.data.frame(list(1:(nrow(mat) - i2), (ncol(mat) -i2):1), stringsAsFactors = TRUE))]", # topleft part
+"mat[as.matrix(as.data.frame(list(1:(nrow(mat) - i2), (1:ncol(mat))[-(1:i2)]), stringsAsFactors = TRUE))]", # topright part
+"mat[as.matrix(as.data.frame(list((1 + i2):nrow(mat), ncol(mat):(1 + i2)), stringsAsFactors = TRUE))]", # bottomright part
+"mat[as.matrix(as.data.frame(list((1 + i2):nrow(mat), 1:(ncol(mat) -i2)), stringsAsFactors = TRUE))]" # bottomleft part
+)
+# empty part detection
+empty.sector <- NULL
+full.sector <- NULL
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+for(i1 in 1:length(sector)){
+tempo.list.diag <- list.diag
+for(i2 in 1:(nrow(mat) - 1)){
+tempo.list.diag[[i2]] <- eval(parse(text = diag.scan[i1]))
+if(ifelse(is.na(empty.cell.string), ! all(is.na(tempo.list.diag[[i2]])), ! (all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = TRUE) & ! (is.na(all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE)))))){ # I had to add this ! (is.na(all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE))) because all(tempo.list.diag[[i2]] == empty.cell.string, na.rm = FALSE) gives NA and not FALSE if one NA in tempo.list.diag[[i2]] -> not good for if()
+full.sector <- c(full.sector, sector[i1])
+break
+}
+}
+if(i2 == nrow(mat) - 1){
+if(all(unlist(lapply(tempo.list.diag, FUN = function(x){if(is.na(empty.cell.string)){is.na(x)}else{x == empty.cell.string}})), na.rm = TRUE)){
+empty.sector <- c(empty.sector, sector[i1])
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") EMPTY SECTOR DETECTED ON THE ", toupper(sector[i1]), " CORNER, FULL OF ", empty.cell.string)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE ", toupper(sector[i1]), " SECTOR, DETECTED AS EMPTY, IS NOT? DIFFERENT VALUES IN THIS SECTOR:\n", paste(names(table(unlist(tempo.list.diag), useNA = "ifany")), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}
+# end empty part detection
+if(length(empty.sector) == 0L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") ACCORDING TO empty.cell.string ARGUMENT (", empty.cell.string, "), mat ARGUMENT MATRIX HAS ZERO EMPTY HALF PART")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+if(length(empty.sector) > 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ACCORDING TO empty.cell.string ARGUMENT (", empty.cell.string, "), mat ARGUMENT MATRIX HAS MORE THAN ONE EMPTY HALF PART (ACCORDING TO THE GRAND DIAGONAL): ", paste(empty.sector, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(any(full.sector %in% empty.sector, na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE FUNCTION HAS DETECTED EMPTY AND NON EMPTY HALF PART IN THE SAME SECTOR: ", paste(full.sector[full.sector %in% empty.sector], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(length(empty.sector) + length(full.sector)!= 4){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE FUNCTION HAS DETECTED MORE OR LESS SECTORS THAN 4:\nHALF SECTORS:", paste(empty.sector, collapse = " "), "\nFULL SECTORS:", paste(full.sector, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") ", toupper(empty.sector), " SECTOR HAS BEEN COMPLETED TO BECOME SYMMETRICAL")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# matrix filling
+for(i2 in 1:(nrow(mat) - 1)){
+if(empty.sector == "topleft"){
+eval(parse(text = paste0(diag.scan[1], " <- ", diag.scan[3])))
+}else if(empty.sector == "topright"){
+eval(parse(text = paste0(diag.scan[2], " <- ", diag.scan[4])))
+}else if(empty.sector == "bottomright"){
+eval(parse(text = paste0(diag.scan[3], " <- ", diag.scan[1])))
+}else if(empty.sector == "bottomleft"){
+eval(parse(text = paste0(diag.scan[4], " <- ", diag.scan[2])))
+}
+}
+# end matrix filling
+}
+if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+return(list(mat = mat, warn = warn))
+}
+
+
+######## fun_permut() #### progressively breaks a vector order
+
+
+fun_permut <- function(
+data1, 
+data2 = NULL, 
+n = NULL, 
+seed = NULL, 
+print.count = 10, 
+text.print = "", 
+cor.method = "spearman", 
+cor.limit = 0.2, 
+warn.print = FALSE, 
+lib.path = NULL
+){
+# AIM
+# reorder the elements of the data1 vector by flipping 2 randomly selected  consecutive positions either:
+# 1) n times (when n is precised) or
+# 2) until the correlation between data1 and data2 decreases down to the cor.limit (0.2 by default). See cor.limit below to deal with negative correlations
+# Example of consecutive position flipping: ABCD -> BACD -> BADC, etc.
+# designed for discrete values, but worls also for continuous values
+# WARNINGS
+# see # https://www.r-bloggers.com/strategies-to-speedup-r-code/ for code speedup
+# the random switch of non consecutive positions (ABCD -> DBCA for instance) does not work very well as the correlation is quickly obtained but the initial vector structure is mainly kept (no much order). Ths code would be: pos <- ini.pos[1:2] ; pos <- sample.int(n = n , size = 2, replace = FALSE) ; tempo.pos[pos] <- tempo.pos[rev(pos)]
+# ARGUMENTS
+# data1: a vector of at least 2 elements. Must be numeric if data2 is specified
+# data2: a numeric vector of same length as data1
+# n: number of times "flipping 2 randomly selected consecutive positions". Ignored if data2 is specified
+# seed: integer number used by set.seed(). Write NULL if random result is required, an integer otherwise. BEWARE: if not NULL, fun_permut() will systematically return the same result when the other parameters keep the same settings
+# print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
+# text.print: optional message to add to the working progress message every print.count loop
+# cor.method: correlation method. Either "pearson", "kendall" or "spearman". Ignored if data2 is not specified
+# cor.limit: a correlation limit (between 0 and 1). Ignored if data2 is not specified. Compute the correlation between data1 and data2, permute the data1 values, and stop the permutation process when the correlation between data1 and data2 decreases down below the cor limit value (0.2 by default). If cor(data1, data2) is negative, then -cor.limit is used and the process stops until the correlation between data1 and data2 increases up over cor.limit (-0.2 by default). BEWARE: write a positive cor.limit even if cor(data1, data2) is known to be negative. The function will automatically uses -cor.limit. If the initial correlation is already below cor.limit (positive correlation) or over -cor.limit (negative correlation), then the data1 value positions are completely randomized (correlation between data1 and data2 is expected to be 0)
+# warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# RETURN
+# a list containing:
+# $data: the modified vector
+# $warn: potential warning messages (in case of negative correlation when data2 is specified). NULL if non warning message
+# $cor: a spearman correlation between the initial positions (1:length(data1) and the final positions if data2 is not specified and the final correlation between data1 and data2 otherwise, according to cor.method
+# $count: the number of loops used
+# REQUIRED PACKAGES
+# lubridate
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# fun_round()
+# EXAMPLES
+# example (1) showing that for loop, used in fun_permut(), is faster than while loop
+# ini.time <- as.numeric(Sys.time()) ; count <- 0 ; for(i0 in 1:1e9){count <- count + 1} ; tempo.time <- as.numeric(Sys.time()) ; tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time)) ; tempo.lapse
+# example (2) showing that for loop, used in fun_permut(), is faster than while loop
+# ini.time <- as.numeric(Sys.time()) ; count <- 0 ; while(count < 1e9){count <- count + 1} ; tempo.time <- as.numeric(Sys.time()) ; tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time)) ; tempo.lapse
+# fun_permut(data1 = LETTERS[1:5], data2 = NULL, n = 100, seed = 1, print.count = 10, text.print = "CPU NB 4")
+# fun_permut(data1 = 101:110, data2 = 21:30, seed = 1, print.count = 1e4, text.print = "", cor.method = "spearman", cor.limit = 0.2)
+# a way to use the cor.limit argument just considering data1
+# obs1 <- 101:110 ; fun_permut(data1 = obs1, data2 = obs1, seed = 1, print.count = 10, cor.method = "spearman", cor.limit = 0.2)
+# fun_permut(data1 = 1:1e3, data2 = 1e3:1, seed = 1, print.count = 1e6, text.print = "", cor.method = "spearman", cor.limit = 0.7)
+# fun_permut(data1 = 1:1e2, data2 = 1e2:1, seed = 1, print.count = 1e3, cor.limit = 0.5)
+# fun_permut(data1 = c(0,0,0,0,0), n = 5, data2 = NULL, seed = 1, print.count = 1e3, cor.limit = 0.5)
+# DEBUGGING
+# data1 = LETTERS[1:5] ; data2 = NULL ; n = 1e6 ; seed = NULL ; print.count = 1e3 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
+# data1 = LETTERS[1:5] ; data2 = NULL ; n = 10 ; seed = 22 ; print.count = 10 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
+# data1 = 101:110 ; data2 = 21:30 ; n = 10 ; seed = 22 ; print.count = 10 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.2 ; warn.print = TRUE ; lib.path = NULL
+# data1 = 1:1e3 ; data2 = 1e3:1 ; n = 20 ; seed = 22 ; print.count = 1e6 ; text.print = "" ; cor.method = "spearman" ; cor.limit = 0.5 ; warn.print = TRUE ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_round", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data1, class = "vector", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & length(data1) < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A VECTOR OF MINIMUM LENGTH 2. HERE IT IS: ", length(data1))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(data2)){
+tempo <- fun_check(data = data1, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
+if(tempo$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 MUST BE A NUMERIC VECTOR IF data2 ARGUMENT IS SPECIFIED")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = data2, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
+if(length(data1) != length(data2)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 AND data2 MUST BE VECTOR OF SAME LENGTH. HERE IT IS ", length(data1)," AND ", length(data2))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else if(is.null(n)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT CANNOT BE NULL IF data2 ARGUMENT IS NULL")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(n)){
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(seed)){
+tempo <- fun_check(data = seed, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = text.print, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = cor.method, options = c("pearson", "kendall", "spearman"), length =1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = cor.limit, class = "vector", mode = "numeric", prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# package checking
+fun_pack(req.package = "lubridate", lib.path = lib.path)
+# end package checking
+# main code
+# code that protects set.seed() in the global environment
+# see also Protocol 100-rev0 Parallelization in R.docx
+if(exists(".Random.seed", envir = .GlobalEnv)){ # if .Random.seed does not exists, it means that no random operation has been performed yet in any R environment
+tempo.random.seed <- .Random.seed
+on.exit(assign(".Random.seed", tempo.random.seed, env = .GlobalEnv))
+}else{
+on.exit(set.seed(NULL)) # inactivate seeding -> return to complete randomness
+}
+set.seed(seed)
+# end code that protects set.seed() in the global environment
+ini.date <- Sys.time() # time of process begin, converted into seconds
+ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
+ini.pos <- 1:length(data1) # positions of data1 before permutation loops
+tempo.pos <- ini.pos # positions of data1 that will be modified during loops
+# pos.selec.seq <- ini.pos[-length(data1)] # selection of 1 position in initial position, without the last because always up permutation (pos -> pos+1 & pos+1 -> pos)
+pos.selec.seq.max <- length(ini.pos) - 1 # max position (used by sample.int() function). See  below for - 1
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+count <- 0
+round <- 0
+BREAK <- FALSE
+tempo.cor <- 0
+if(is.null(data2)){
+if(length(table(data1)) == 1L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data1 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data1)))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
+}else{
+if(print.count > n){
+print.count <- n
+}
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP OF ", n, " LOOPS INITIATED | LOOP COUNT: ", format(count, big.mark=",")))
+print.count.loop <- logical(length = print.count)
+print.count.loop[length(print.count.loop)] <- TRUE # not this to avoid long vector, but not forget to reset during printing: print.count.loop[(1:trunc(n / print.count) * print.count)] <- TRUE # counter to speedup
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.date.loop <- Sys.time()
+tempo.time.loop <- as.numeric(tempo.date.loop)
+for(i3 in 1:n){
+count.loop <- count.loop + 1
+pos2 <- pos[count.loop] # selection of 1 position
+tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+if(print.count.loop[count.loop]){
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
+final.loop <- (tempo.time - tempo.time.loop) / i3 * n # expected duration in seconds
+final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP ", i3, " / ", n, " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+}
+}
+count <- count + n # out of the loop to speedup
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP ENDED | LOOP COUNT: ", format(count, big.mark=",")))
+cat("\n\n")
+}
+}else{
+if(length(table(data1)) == 1L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data1 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data1)))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
+tempo.cor <- 1
+}else if(length(table(data2)) == 1L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO PERMUTATION PERFORMED BECAUSE data2 ARGUMENT SEEMS TO BE MADE OF IDENTICAL ELEMENTS: ", names(table(data2)))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
+tempo.cor <- 1
+}else{
+cor.ini <- cor(x = data1, y = data2, use = "pairwise.complete.obs", method = cor.method)
+tempo.cor <- cor.ini # correlation that will be modified during loops
+neg.cor <- FALSE
+if(tempo.cor < 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") INITIAL ", toupper(cor.method), " CORRELATION BETWEEN data1 AND data2 HAS BEEN DETECTED AS NEGATIVE: ", tempo.cor, ". THE LOOP STEPS WILL BE PERFORMED USING POSITIVE CORRELATIONS BUT THE FINAL CORRELATION WILL BE NEGATIVE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
+neg.cor <- TRUE
+tempo.cor <- abs(tempo.cor)
+cor.ini <- abs(cor.ini)
+}
+if(tempo.cor < cor.limit){ # randomize directly all the position to be close to correlation zero
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") INITIAL ABSOLUTE VALUE OF THE ", toupper(cor.method), " CORRELATION ", fun_round(tempo.cor), " BETWEEN data1 AND data2 HAS BEEN DETECTED AS BELOW THE CORRELATION LIMIT PARAMETER ", cor.limit, "\nTHE data1 SEQUENCE HAS BEEN COMPLETELY RANDOMIZED TO CORRESPOND TO CORRELATION ZERO")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn))) #
+for(i4 in 1:5){ # done 5 times to be sure of the complete randomness
+tempo.pos <- sample(x = tempo.pos, size = length(tempo.pos), replace = FALSE)
+}
+count <- count + 5 # out of the loop to speedup
+}else{
+# smallest correlation decrease
+count <- count + 1 # 1 and not 0 because already 1 performed just below
+pos <- sample.int(n = pos.selec.seq.max , size = 1, replace = TRUE) # selection of 1 position # pos.selec.seq.max  because selection of 1 position in initial position, without the last because always up permutation (pos -> pos+1 & pos+1 -> pos)
+tempo.pos[c(pos + 1, pos)] <- tempo.pos[c(pos, pos + 1)]
+tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
+smallest.cor.dec <- cor.ini - tempo.cor
+# end smallest correlation decrease
+# going out of tempo.cor == cor.ini
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "CORRELATION DECREASE AFTER A SINGLE PERMUTATION: ", fun_round(smallest.cor.dec, 4)))
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP -> GOING OUT FROM EQUALITY | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
+print.count.loop <- logical(length = print.count)
+print.count.loop[length(print.count.loop)] <- TRUE # counter to speedup
+count.loop <- 0 # 
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.date.loop <- Sys.time()
+tempo.time.loop <- as.numeric(tempo.date.loop)
+while(tempo.cor == cor.ini){ # to be out of equality between tempo.cor and cor.ini at the beginning (only valid for very long vector)
+count <- count + 1
+count.loop <- count.loop + 1
+pos2 <- pos[count.loop]
+tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
+if(print.count.loop[count.loop]){
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP", format(count.loop, big.mark=","), " / ? | COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TIME SPENT: ", tempo.lapse))
+}
+}
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FIRST WHILE LOOP STEP END | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TOTAL SPENT TIME: ", tempo.lapse))
+if(tempo.cor < cor.limit){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE FIRST FOR & WHILE LOOP STEPS HAVE BEEN TOO FAR AND SUBSEQUENT LOOP STEPS WILL NOT RUN")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end going out of tempo.cor == cor.ini
+# estimation of the average correlation decrease per loop on x loops and for loop execution
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE/FOR LOOPS INITIATION | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
+count.est <- 1e5
+first.round <- TRUE
+GOBACK <- FALSE
+while(tempo.cor > cor.limit){
+round <- round + 1
+# estimation step
+if(first.round == TRUE){
+first.round <- FALSE
+cor.dec.per.loop <- numeric(length = 5)
+loop.nb.est <- Inf
+cor.est.ini <- tempo.cor
+cor.est <- numeric(length = 5)
+for(i6 in 1:5){ # connected to cor.dec.per.loop
+tempo.pos.est <- tempo.pos
+pos <- sample.int(n = pos.selec.seq.max , size = count.est, replace = TRUE) # selection of n position
+for(i7 in 1:count.est){
+pos2 <- pos[i7] # selection of 1 position
+tempo.pos.est[c(pos2 + 1, pos2)] <- tempo.pos.est[c(pos2, pos2 + 1)]
+}
+tempo.cor.est <- abs(cor(x = data1[tempo.pos.est], y = data2, use = "pairwise.complete.obs", method = cor.method))
+cor.est[i6] <- tempo.cor.est
+tempo.cor.dec.per.loop <- (cor.est.ini - tempo.cor.est) / count.est # correlation decrease per loop
+if(is.na(tempo.cor.dec.per.loop) | ! is.finite(tempo.cor.dec.per.loop)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2\ncor.est.ini: ", cor.est.ini, "\ntempo.cor.est: ", tempo.cor.est)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+cor.dec.per.loop[i6] <- tempo.cor.dec.per.loop
+}
+cor.est <- cor.est[which.max(cor.dec.per.loop)] # max to avoid to go to far with for loop (tempo.cor below tempo.limit)
+cor.dec.per.loop <- max(cor.dec.per.loop, na.rm = TRUE) # max to avoid to go to far with for loop (tempo.cor below tempo.limit)
+loop.nb.est <- round((tempo.cor - cor.limit) / cor.dec.per.loop)
+}else{
+if(GOBACK == TRUE){
+loop.nb.est <- round(loop.nb.est / 2)
+}else{
+cor.dec.per.loop <- (cor.ini - tempo.cor) / count
+loop.nb.est <- round((tempo.cor - cor.limit) / cor.dec.per.loop)
+}
+}
+# end estimation step
+# loop step
+if(is.na(loop.nb.est) | ! is.finite(loop.nb.est)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1\nloop.nb.est: ", loop.nb.est, "\ncor.ini: ", cor.ini, "\ntempo.cor: ", tempo.cor, "\ncor.limit: ", cor.limit, "\ncor.dec.per.loop: ", cor.dec.per.loop)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(loop.nb.est > 1e4){ # below -> leave the while loop
+tempo.pos.secu <- tempo.pos
+count.secu <- count
+tempo.cor.secu <- tempo.cor
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "INITIAL SETTINGS BEFORE ROUND: ", round, " | LOOP COUNT: ", format(count, big.mark=","), " | GO BACK: ", GOBACK, " | LOOP NUMBER ESTIMATION: ", format(loop.nb.est, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
+print.count.loop <- logical(length = print.count)
+print.count.loop[length(print.count.loop)] <- TRUE # not this to avoid long vector, but not forget to reset during printing: print.count.loop[(1:trunc(n / print.count) * print.count)] <- TRUE # counter to speedup
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.date.loop <- Sys.time()
+tempo.time.loop <- as.numeric(tempo.date.loop)
+for(i6 in 1:loop.nb.est){
+count.loop <- count.loop + 1
+pos2 <- pos[count.loop] # selection of 1 position
+tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+if(print.count.loop[count.loop]){
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
+final.loop <- (tempo.time - tempo.time.loop) / i6 * loop.nb.est # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
+final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FOR LOOP | ROUND ", round, " | LOOP: ", format(i6, big.mark=","), " / ", format(loop.nb.est, big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+}
+}
+count <- count + loop.nb.est # out of the loop to speedup
+tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
+if(tempo.cor > tempo.cor.secu | ((tempo.cor - cor.limit) < 0 & abs(tempo.cor - cor.limit) > smallest.cor.dec * round(log10(max(ini.pos, na.rm = TRUE))))){
+GOBACK <- TRUE
+tempo.pos <- tempo.pos.secu
+count <- count.secu
+tempo.cor <- tempo.cor.secu
+}else{
+GOBACK <- FALSE
+}
+}else{
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "FINAL WHILE LOOP | LOOP COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4)))
+print.count.loop <- logical(length = print.count)
+print.count.loop[length(print.count.loop)] <- TRUE # counter to speedup
+count.loop <- 0 # 
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # selection of random positions. BEWARE: n = pos.selec.seq.max because already - 1 (see above) but is connected to tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.cor.loop <- tempo.cor
+tempo.date.loop <- Sys.time()
+tempo.time.loop <- as.numeric(tempo.date.loop)
+while(tempo.cor > cor.limit){
+count <- count + 1
+count.loop <- count.loop + 1
+pos2 <- pos[count.loop]
+tempo.pos[c(pos2 + 1, pos2)] <- tempo.pos[c(pos2, pos2 + 1)]
+tempo.cor <- abs(cor(x = data1[tempo.pos], y = data2, use = "pairwise.complete.obs", method = cor.method))
+if(print.count.loop[count.loop]){
+count.loop <- 0
+pos <- sample.int(n = pos.selec.seq.max , size = print.count, replace = TRUE) # BEWARE: never forget to resample here
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - tempo.time.loop))
+final.loop <- (tempo.time - tempo.time.loop) / (tempo.cor.loop - tempo.cor) * (tempo.cor - cor.limit) # expected duration in seconds # tempo.cor.loop - tempo.cor always positive and tempo.cor decreases progressively starting from tempo.cor.loop
+final.exp <- as.POSIXct(final.loop, origin = tempo.date.loop)
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE LOOP | LOOP NB: ", format(count.loop, big.mark=","), " | COUNT: ", format(count, big.mark=","), " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+}
+}
+}
+}
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+cat(paste0("\n", ifelse(text.print == "", "", paste0(text.print, " | ")), "WHILE/FOR LOOPS END | LOOP COUNT: ", format(count, big.mark=","), " | NB OF ROUNDS: ", round, " | CORRELATION LIMIT: ", fun_round(cor.limit, 4), " | ABS TEMPO CORRELATION: ", fun_round(tempo.cor, 4), " | TOTAL SPENT TIME: ", tempo.lapse))
+}
+tempo.cor <- ifelse(neg.cor == TRUE, -tempo.cor, tempo.cor)
+}
+}
+cat("\n\n")
+if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE), add = TRUE)
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+output <- list(data = data1[tempo.pos], warn = warn, cor = if(is.null(data2)){cor(ini.pos, tempo.pos, method = "spearman")}else{tempo.cor}, count = count)
+return(output)
+}
+
+
+######## fun_slide() #### return a computation made on a vector using a sliding window
+
+
+fun_slide <- function(
+data, 
+window.size, 
+step, 
+from = NULL, 
+to = NULL, 
+fun, 
+args = NULL, 
+boundary = "left", 
+parall = FALSE, 
+thread.nb = NULL, 
+print.count = 100, 
+res.path = NULL, 
+lib.path = NULL, 
+verbose = TRUE, 
+cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
+){
+# AIM
+# return a computation made on a vector using a sliding window
+# WARNINGS
+# The function uses two strategies, depending on the amout of memory required which depends on the data, window.size and step arguments. The first one uses lapply(), is generally fast but requires lots of memory. The second one uses a parallelized loop. The choice between the two strategies is automatic if parall argument is FALSE, and is forced toward parallelization if parall argument is TRUE
+# The parall argument forces the parallelization, which is convenient when the data argument is big, because the lapply() function is sometimes slower than the parallelization
+# Always use the env argument when fun_slide() is used inside functions
+# ARGUMENTS
+# data: vector, matrix, table or array of numeric values (mode must be numeric). Inf not allowed. NA will be removed before computation
+# window.size: single numeric value indicating the width of the window sliding across data (in the same unit as data value)
+# step: single numeric value indicating the step between each window (in the same unit as data value). Cannot be larger than window.size
+# from: value of the left boundary of the first sliding window. If NULL, min(data) is used. The first window will strictly have from or min(data) as left boundary
+# to: value of the right boundary of the last sliding window. If NULL, max(data) is used. Warning: (1) the final last window will not necessary have to|max(data) as right boundary. In fact the last window will be the one that contains to|max(data) for the first time, i.e., min[from|min(data) + window.size + n * step >= to|max(data)]; (2) In fact, the >= in min[from|min(data) + window.size + n * step >= to|max(data)] depends on the boundary argument (>= for "right" and > for "left"); (3) to have the rule (1) but for the center of the last window, use to argument as to = to|max(data) + window.size / 2
+# fun: function or character string (without brackets) indicating the name of the function to apply in each window. Example: fun = "mean", or fun = mean
+# args: character string of additional arguments of fun (separated by a comma between the quotes). Example args = "na.rm = TRUE" for fun = mean. Ignored if NULL
+# boundary: either "left" or "right". Indicates if the sliding window includes values equal to left boundary and exclude values equal to right boundary ("left") or the opposite ("right")
+# parall: logical. Force parallelization ?
+# thread.nb: numeric value indicating the number of threads to use if ever parallelization is required. If NULL, all the available threads will be used. Ignored if parall is FALSE
+# print.count: interger value. Print a working progress message every print.count during loops. BEWARE: can increase substentially the time to complete the process using a small value, like 10 for instance. Use Inf is no loop message desired
+# res.path: character string indicating the absolute pathway where the parallelization log file will be created if parallelization is used. If NULL, will be created in the R current directory
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# verbose: logical. Display messages?
+# cute.path: character string indicating the absolute path of the cute.R file. Will be remove when cute will be a package. Ignored if parall is FALSE
+# RETURN
+# a data frame containing
+#$left : the left boundary of each window (in the unit of the data argument)
+#$right : the right boundary of each window (in the unit of data argument)
+#$center : the center of each window (in the unit of data argument)
+#$value : the computed value by the fun argument in each window)
+# REQUIRED PACKAGES
+# lubridate
+# parallel if parall arguemtn is TRUE (included in the R installation packages but not automatically loaded)
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_get_message
+# fun_pack()
+# EXAMPLES
+# fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "left")
+# fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "right") # effect of boundary argument
+# fun_slide(data = c(1:10, 100:110, 500), window.size = 5, step = 2, fun = length, boundary = "left", parall = TRUE) # effect of parall argument
+# DEBUGGING
+# data = c(1:10, 100:110, 500) ; window.size = 5 ; step = 2 ; from = NULL ; to = NULL ; fun = length ; args = NULL ; boundary = "left" ; parall = FALSE ; thread.nb = NULL ; print.count = 100 ; res.path = NULL ; lib.path = NULL ; verbose = TRUE ; env = NULL ; cute.path = "C:\\Users\\Gael\\Documents\\Git_projects\\cute_little_R_functions\\cute_little_R_functions.R"
+# data = lag.pos; window.size = window.size; step = step; fun = length; from = min(a$pos); to = max(a$pos)
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check", 
+"fun_get_message", 
+"fun_pack"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words
+# end reserved words
+# arg with no default values
+mandat.args <- c(
+"data", 
+"window.size", 
+"step", 
+"fun"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data, mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = window.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = step, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(from)){
+tempo <- fun_check(data = from, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(to)){
+tempo <- fun_check(data = to, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo1 <- fun_check(data = fun, class = "vector", mode = "character", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = fun, class = "function", length = 1, fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": fun ARGUMENT MUST BE A FUNCTION OR A CHARACTER STRING OF THE NAME OF A FUNCTION")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(args)){
+tempo <- fun_check(data = args, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = boundary, options = c("left", "right"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = parall, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(parall == TRUE){
+if( ! is.null(thread.nb)){
+tempo <- fun_check(data = thread.nb, typeof = "integer", double.as.integer.allowed = TRUE, neg.values = FALSE, length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & thread.nb < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": thread.nb PARAMETER MUST EQUAL OR GREATER THAN 1: ", thread.nb)
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+tempo <- fun_check(data = print.count, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if( ! is.null(res.path)){
+tempo <- fun_check(data = res.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = verbose, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = cute.path, class = "vector", typeof = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# new environment
+env.name <- paste0("env", as.numeric(Sys.time()))
+if(exists(env.name, where = -1)){ # verify if still ok when fun_info() is inside a function
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE)) # data assigned in a new envir for test
+}
+# end new environment
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS", "THIS ARGUMENT"), " CANNOT JUST BE NA:", paste0(tempo.arg[tempo.log], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"data", 
+"window.size", 
+"step", 
+# "from", # because can be NULL
+# "to", # because can be NULL
+"fun", 
+# "args", # because can be NULL
+"boundary", 
+"parall", 
+# "thread.nb", # because can be NULL
+"print.count", 
+# "res.path", # because can be NULL
+# "lib.path", # because can be NULL
+"verbose", 
+"cute.path"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+# end warning initiation
+# other checkings
+if(length(data) == 0){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT CANNOT BE LENGTH 0")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(any( ! is.finite(data))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT CANNOT CONTAIN Inf VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if(step > window.size){
+tempo.cat <- paste0("ERROR IN ", function.name, ": step ARGUMENT MUST BE LOWER THAN window.size ARGUMENT\nstep: ", paste(step, collapse = " "), "\nwindow.size: ", paste(window.size, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+if( ! is.null(res.path)){
+if( ! all(dir.exists(res.path))){ # separation to avoid the problem of tempo$problem == FALSE and res.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE res.path ARGUMENT DOES NOT EXISTS:\n", paste(res.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+}else{
+res.path <- getwd() # working directory
+}
+if( ! is.null(lib.path)){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE)
+}
+}
+if(grepl(x = cute.path, pattern = "^http")){
+tempo.error1 <- any(grepl(x = fun_get_message(data = "source(cute.path)", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE)), pattern = "^[Ee]rror"))
+tempo.error2 <- FALSE
+}else{
+tempo.error1 <- FALSE
+tempo.error2 <- ! file.exists(cute.path)
+}
+if(tempo.error1 | tempo.error2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(grepl(x = cute.path, pattern = "^http"), "URL", "FILE"), " PATH INDICATED IN THE cute.path PARAMETER DOES NOT EXISTS:\n", cute.path)
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+# end other checkings
+# reserved word checking
+# end reserved word checking
+# end second round of checking and data preparation
+# package checking
+fun_pack(req.package = c("lubridate"), lib.path = lib.path)
+fun_pack(req.package = c("parallel"), lib.path = lib.path)
+# end package checking
+# main code
+if(verbose == TRUE){
+cat("\nfun_slide JOB IGNITION\n")
+}
+ini.date <- Sys.time()
+ini.time <- as.numeric(ini.date) # time of process begin, converted into seconds
+fun <- match.fun(fun) # make fun <- get(fun) is fun is a function name written as character string of length 1
+if(boundary == "left"){
+left <- ">="
+right <- "<"
+right.last.wind <- ">"
+}else if(boundary == "right"){
+left <- ">"
+right <- "<="
+right.last.wind <- ">="
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+data <- as.vector(data)
+data <- sort(data, na.last = NA) # NA removed
+wind <- data.frame(left = seq(from = if(is.null(from)){min(data, na.rm = TRUE)}else{from}, to = if(is.null(to)){max(data, na.rm = TRUE)}else{to}, by = step), stringsAsFactors = TRUE)
+wind <- data.frame(wind, right = wind$left + window.size, stringsAsFactors = TRUE)
+wind <- data.frame(wind, center = (wind$left + wind$right) / 2, stringsAsFactors = TRUE)
+if(all(wind$right < if(is.null(to)){max(data, na.rm = TRUE)}else{to})){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 2")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# The 3 next lines is for the rule of to argument with center (see to argument description)
+# if(any(wind$center > max(data, na.rm = TRUE))){
+# wind <- wind[ ! wind$center > max(data, na.rm = TRUE),]
+# }
+if(sum(get(right.last.wind)(wind$right, if(is.null(to)){max(data, na.rm = TRUE)}else{to}), na.rm = TRUE) > 1){  # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+tempo.log <- get(right.last.wind)(wind$right, if(is.null(to)){max(data, na.rm = TRUE)}else{to}) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+tempo.log[min(which(tempo.log), na.rm = TRUE)] <- FALSE # convert the first left boundary that goes above max(data, na.rm = TRUE) to FALSE to keep it (the next ones will be removed)
+wind <- wind[ ! tempo.log,]
+}
+
+# test if lapply can be used
+if(parall == FALSE){
+# new environment
+env.name <- paste0("env", ini.time)
+if(exists(env.name, where = -1)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ENVIRONMENT env.name ALREADY EXISTS. PLEASE RERUN ONCE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+assign(env.name, new.env())
+assign("wind", wind, envir = get(env.name, env = sys.nframe(), inherit = FALSE))
+assign("data", data, envir = get(env.name, env = sys.nframe(), inherit = FALSE))
+}
+# end new environment
+tempo.message <- fun_get_message(data="lapply(X = wind$left, Y = data, FUN = function(X, Y){res <- get(left)(Y, X) ; return(res)})", kind = "error", header = FALSE, env = get(env.name, env = sys.nframe(), inherit = FALSE), print.no = FALSE) # no env = sys.nframe(), inherit = FALSE in get(left) because look for function in the classical scope
+rm(env.name) # optional, because should disappear at the end of the function execution
+}else{
+tempo.message <- "ERROR" # with this, force the parallelization by default
+}
+# end test if lapply can be used
+if( ! any(grepl(x = tempo.message, pattern = "ERROR.*"))){
+left.log <- lapply(X = wind$left, Y = data, FUN = function(X, Y){
+res <- get(left)(Y, X) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+return(res)
+})
+right.log <- lapply(X = wind$right, Y = data, FUN = function(X, Y){
+res <- get(right)(Y, X) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+return(res)
+})
+log <- mapply(FUN = "&", left.log, right.log, SIMPLIFY = FALSE)
+output <- eval(parse(text = paste0("sapply(lapply(log, FUN = function(X){(data[X])}), FUN = fun", if( ! is.null(args)){paste0(", ", args)}, ")"))) # take the values of the data vector according to log (list of logical, each compartment of length(data)) and apply fun with args of fun
+if(length(output) != nrow(wind)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+output <- data.frame(wind, value = output, stringsAsFactors = TRUE)
+}
+}else{
+if(verbose == TRUE){
+tempo.cat <- paste0("PARALLELIZATION INITIATED AT: ", ini.date)
+cat(paste0("\n", tempo.cat, "\n"))
+}
+tempo.thread.nb = parallel::detectCores(all.tests = FALSE, logical = TRUE) # detect the number of threads
+if( ! is.null(thread.nb)){
+if(tempo.thread.nb < thread.nb){
+thread.nb <- tempo.thread.nb
+if(verbose == TRUE){
+tempo.cat <- paste0("ONLY: ", tempo.thread.nb, " THREADS AVAILABLE")
+cat(paste0("\n", tempo.cat, "\n"))
+}
+}
+}else{
+thread.nb <- tempo.thread.nb
+}
+if(verbose == TRUE){
+tempo.cat <- paste0("NUMBER OF THREADS USED: ", thread.nb)
+cat(paste0("\n    ", tempo.cat, "\n"))
+}
+Clust <- parallel::makeCluster(thread.nb, outfile = paste0(res.path, "/fun_slide_parall_log.txt")) # outfile to print or cat during parallelization (only possible in a file, outfile = "" do not work on windows)
+cluster.list <- parallel::clusterSplit(Clust, 1:nrow(wind)) # split according to the number of cluster
+if(verbose == TRUE){
+tempo.cat <- paste0("SPLIT OF TEST NUMBERS IN PARALLELISATION:")
+cat(paste0("\n    ", tempo.cat, "\n"))
+str(cluster.list) # using print(str()) add a NULL below the result
+cat("\n")
+}
+paral.output.list <- parallel::clusterApply( #
+cl = Clust,
+x = cluster.list,
+function.name = function.name, 
+data = data, 
+FUN = fun, # because fun argument of clusterApply
+args = args, 
+thread.nb = thread.nb, 
+print.count = print.count, 
+wind = wind, 
+left = left, 
+right = right, 
+res.path = res.path, 
+lib.path = lib.path, 
+verbose = verbose, 
+env = env, 
+cute.path = cute.path, 
+fun = function(
+x, 
+function.name, 
+data, 
+FUN, 
+args, 
+thread.nb, 
+print.count, 
+wind, 
+left, 
+right, 
+res.path, 
+lib.path, 
+verbose, 
+env, 
+cute.path
+){
+# check again: very important because another R
+process.id <- Sys.getpid()
+cat(paste0("\nPROCESS ID ", process.id, " -> TESTS ", x[1], " TO ", x[length(x)], "\n"))
+source(cute.path, local = .GlobalEnv)
+fun_pack(req.package = "lubridate", lib.path = lib.path, load = TRUE) # load = TRUE to be sure that functions are present in the environment. And this prevent to use R.lib.path argument of fun_python_pack()
+# end check again: very important because another R
+ini.date <- Sys.time()
+ini.time <- as.numeric(ini.date) # time of process begin, converted into 
+output <- NULL
+print.count.loop <- 0
+for(i4 in 1:length(x)){
+print.count.loop <- print.count.loop + 1
+log <- get(left)(data, wind$left[x[i4]]) & get(right)(data, wind$right[x[i4]]) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+output <- c(output, eval(parse(text = paste0("FUN(data[log]", if( ! is.null(args)){paste0(", ", args)}, ")"))))
+if(verbose == TRUE){
+if(print.count.loop == print.count){
+print.count.loop <- 0
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+final.loop <- (tempo.time - ini.time) / i4 * length(x) # expected duration in seconds # intra nb.compar loop lapse: time lapse / cycles done * cycles remaining
+final.exp <- as.POSIXct(final.loop, origin = ini.date)
+cat(paste0("\nIN PROCESS ", process.id, " | LOOP ", format(i4, big.mark=","), " / ", format(length(x), big.mark=","), " | TIME SPENT: ", tempo.lapse, " | EXPECTED END: ", final.exp))
+}
+if(i4 == length(x)){
+tempo.time <- as.numeric(Sys.time())
+tempo.lapse <- round(lubridate::seconds_to_period(tempo.time - ini.time))
+cat(paste0("\nPROCESS ", process.id, " ENDED | LOOP ", format(i4, big.mark=","), " / ", format(length(x), big.mark=","), " | TIME SPENT: ", tempo.lapse, "\n\n"))
+}
+}
+}
+wind <- wind[x, ]
+if(length(output) != nrow(wind)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+output <- data.frame(wind, value = output, stringsAsFactors = TRUE)
+return(output)
+}
+}
+)
+parallel::stopCluster(Clust)
+# result assembly
+output <- data.frame()
+for(i2 in 1:length(paral.output.list)){ # compartment relatives to each parallelization
+output <- rbind(output, paral.output.list[[i2]], stringsAsFactors = TRUE)
+}
+# end result assembly
+if(nrow(output) != nrow(wind)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 5\nlength(output): ", length(output), "\nnrow(wind): ", nrow(wind))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+output <- output[order(output$left), ]
+}
+}
+if(verbose == TRUE){
+end.date <- Sys.time()
+end.time <- as.numeric(end.date)
+total.lapse <- round(lubridate::seconds_to_period(end.time - ini.time))
+cat(paste0("\nfun_slide JOB END\n\nTIME: ", end.date, "\n\nTOTAL TIME LAPSE: ", total.lapse, "\n\n\n"))
+}
+return(output)
+}
+
+
+
+
+######## fun_codon2aa() #### convert codon to amino acid using standard genetic code
+
+
+fun_codon2aa <- function(
+data,
+display = FALSE
+){
+# AIM
+# Convert codon to amino acid using standard genetic code indicated in https://en.wikipedia.org/wiki/DNA_and_RNA_codon_tables
+# WARNINGS
+# None
+# ARGUMENTS
+# data: single caracter string of three characters, or vector of three caracters, indicating the DNA codon (only "A", "T", "G" and "C" allowed). Case insensitive. Omitted if display argument is TRUE
+# display: logical. Display the whole genetic table? if TRUE, override data
+# RETURN
+# The 1 letter uppercase amino acid of the submitted codon or the whole table if display argument is TRUE
+# REQUIRED PACKAGES
+# None
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# fun_check()
+# EXAMPLE
+# fun_codon2aa(data = "ATC", display = TRUE)
+# see http
+# DEBUGGING
+# data = "atg" ; display = FALSE
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words
+# end reserved words
+# arg with no default values
+mandat.args <- c(
+"data"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data, class = "vector", typeof = "character", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = display, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){ # normally no NA
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"data", 
+"display"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+# end warning initiation
+# other checkings
+if(length(data) == 1L){
+data <- unlist(strsplit(data, split = ""))
+}else if(length(data) != 3L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A STRING OF THREE CHARACTERS OR A VECTOR OF THREE CHARACTERS, MADE OF \"A\", \"C\", \"G\", \"T\" ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! all(toupper(data) %in% c("A", "C", "G","T"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A STRING OF THREE CHARACTERS OR A VECTOR OF THREE CHARACTERS, MADE OF \"A\", \"C\", \"G\", \"T\" ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end other checkings
+# reserved word checking
+# end reserved word checking
+# end second round of checking and data preparation
+# package checking
+# end package checking
+# main code
+# standard genetic code
+sgc <- array(
+c(
+"F", "L", "I", "V",
+"S", "P", "T", "A",
+"Y", "H", "N", "D",
+"C", "R", "S", "G",
+
+"F", "L", "I", "V",
+"S", "P", "T", "A",
+"Y", "H", "N", "D",
+"C", "R", "S", "G",
+
+"L", "L", "I", "V",
+"S", "P", "T", "A",
+"stop", "Q", "K", "E",
+"stop", "R", "R", "G",
+
+"L", "L", "M", "V",
+"S", "P", "T", "A",
+"stop", "Q", "K", "E",
+"W", "R", "R", "G"
+), 
+dim = c(4, 4, 4),
+dimnames = list(
+first = c("T", "C", "A", "G"), 
+second = c("T", "C", "A", "G"), 
+third = c("T", "C", "A", "G")
+)
+)
+# end standard genetic code
+if(display == TRUE){
+output <- sgc
+}else{
+data <- toupper(data)
+output <- eval(parse(text = paste0("sgc['", paste0(data, collapse = "','"), "']")))
+}
+return(output)
+}
+
+
+######## fun_codon_finder() #### gives the codon number and position in the codon of nucleotid positions
+
+
+fun_codon_finder <- function(
+pos, 
+begin, 
+end
+){
+# AIM
+# gives the codon number and position in the codon of nucleotid positions
+# WARNINGS
+# Only for coding sequences (no introns): ((end - begin) + 1) / 3 must be an integer (i.e., modulo zero)
+# Negatives positions allowed but this implies that one base has the position 0 in the sequence
+# ARGUMENTS
+# pos: vector of integers indicating the positions of nucleotids in a sequence. Must be between begin and end arguments
+# begin: single integer indicating the position of the first base of the coding sequence
+# end: single indicating the position of the last base of the coding sequence
+# RETURN
+# a data frame with column names:
+# pos: values of the pos argument
+# codon_nb: the codon number in the CDS encompassing the pos value
+# codon_pos: the position of pos in the codon (either 1, 2 or 3)
+# codon_begin: the first base position of the codon
+# codon_end: the last base position of the codon
+# REQUIRED PACKAGES
+# None
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# fun_check()
+# EXAMPLE
+# fun_codon_finder(c(5, 6, 8, 10), begin = 5, end = 10)
+# fun_codon_finder(c(0, 5, 6, 8, 10), begin = -2, end = 12)
+# see http
+# DEBUGGING
+# pos = c(5, 6, 8, 10) ; begin = 5 ; end = 10
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words
+# end reserved words
+# arg with no default values
+mandat.args <- c(
+"pos", 
+"begin", 
+"end"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = pos, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = begin, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = end, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){ # normally no NA
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"pos", 
+"begin", 
+"end"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+# end warning initiation
+# other checkings
+if(begin >= end){
+tempo.cat <- paste0("ERROR IN ", function.name, ": end ARGUMENT MUST BE STRICTLY GREATER THAN begin ARGUMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if((end - begin + 1) %% 3 != 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ((end - begin) + 1) / 3 MUST BE AN INTEGER (I.E., MODULO ZERO)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(pos < begin | pos > end)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": pos ARGUMENT VALUES MUST BE BETWEEN begin AND end ARGUMENT VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end other checkings
+# reserved word checking
+# end reserved word checking
+# end second round of checking and data preparation
+# package checking
+# end package checking
+# main code
+first <- seq.int(from = begin, to = end, by = 3)
+last <- seq.int(from = begin + 2, to = end, by = 3)
+tempo <- lapply(X = pos, FUN = function(x = X){
+tempo.log <- x >= first & x <= last
+if(sum(tempo.log, na.rm = TRUE) != 1){ # check that 1 possible TRUE
+tempo.cat <- paste0("ERROR IN ", function.name, ": INTERNAL ERROR. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+codon_nb <- which(tempo.log)
+codon_pos <- as.integer((x - (begin + (codon_nb - 1) * 3) + 1))
+codon_begin <- as.integer(first[tempo.log])
+codon_end <- as.integer(last[tempo.log])
+}
+return(data.frame(codon_nb = codon_nb, codon_pos = codon_pos, codon_begin = codon_begin, codon_end = codon_end))
+})
+tempo <- do.call("rbind", tempo)
+output <- data.frame(pos = as.integer(pos), tempo)
+return(output)
+}
+
+
+################ Graphics management
+
+
+# this order can be used:
+# fun_width()
+# fun_open()
+# fun_prior_plot() # not for ggplot2
+# plot() or any other plotting
+# fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
+# fun_close()
+
+
+######## fun_width() #### window width depending on classes to plot
+
+
+fun_width <- function(
+class.nb, 
+inches.per.class.nb = 1, 
+ini.window.width = 7, 
+inch.left.space, 
+inch.right.space, 
+boundarie.space = 0.5
+){
+# AIM
+# rescale the width of a window to open depending on the number of classes to plot
+# can be used for height, considering that it is as if it was a width
+# this order can be used:
+# fun_width()
+# fun_open()
+# fun_prior_plot() # not for ggplot2
+# plot() or any other plotting
+# fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
+# fun_close()
+# ARGUMENTS
+# class.nb: number of class to plot
+# inches.per.class.nb: number of inches per unit of class.nb. 2 means 2 inches for each boxplot for instance
+# ini.window.width:initial window width in inches
+# inch.left.space: left horizontal margin of the figure region (in inches)
+# inch.right.space: right horizontal margin of the figure region (in inches)
+# boundarie.space: space between the right and left limits of the plotting region and the plot (0.5 means half a class width)
+# RETURN
+# the new window width in inches
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_width(class.nb = 10, inches.per.class.nb = 0.2, ini.window.width = 7, inch.left.space = 1, inch.right.space = 1, boundarie.space = 0.5)
+# DEBUGGING
+# class.nb = 10 ; inches.per.class.nb = 0.2 ; ini.window.width = 7 ; inch.left.space = 1 ; inch.right.space = 1 ; boundarie.space = 0.5 # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = class.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = inches.per.class.nb, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = ini.window.width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = inch.left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = inch.right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = boundarie.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+range.max <- class.nb + boundarie.space # the max range of the future plot
+range.min <- boundarie.space # the min range of the future plot
+window.width <- inch.left.space + inch.right.space + inches.per.class.nb * (range.max - range.min)
+return(window.width)
+}
+
+
+######## fun_open() #### open a GUI or pdf graphic window
+
+
+fun_open <- function(
+pdf = TRUE, 
+pdf.path = "working.dir", 
+pdf.name = "graph", 
+width = 7, 
+height = 7, 
+paper = "special", 
+pdf.overwrite = FALSE, 
+rescale = "fixed", 
+remove.read.only = TRUE, 
+return.output = FALSE
+){
+# AIM
+# open a pdf or screen (GUI) graphic window and return initial graphic parameters
+# this order can be used:
+# fun_width()
+# fun_open()
+# fun_prior_plot() # not for ggplot2
+# plot() or any other plotting
+# fun_post_plot() if fun_prior_plot() has been used # not for ggplot2
+# fun_close()
+# WARNINGS
+# On Linux, use pdf = TRUE, if (GUI) graphic window is not always available, meaning that X is not installed (clusters for instance). Use X11() in R to test if available
+# ARGUMENTS:
+# pdf: logical. Use pdf display? If FALSE, a GUI is opened
+# pdf.path: where the pdf is saved (do not terminate by / or \\). Write "working.dir" if working directory is required (default). Ignored if pdf == FALSE
+# pdf.name: name of the pdf file containing the graphs (the .pdf extension is added by the function, if not detected in the name end). Ignored if pdf == FALSE
+# width: width of the window (in inches)
+# height: height of the window (in inches)
+# paper: paper argument of the pdf function (paper format). Only used for pdf(). Either "a4", "letter", "legal", "us", "executive", "a4r", "USr" or "special". If "special", means that the paper dimension will be width and height. With another paper format, if width or height is over the size of the paper, width or height will be modified such that the plot is adjusted to the paper dimension (see $dim in the returned list below to see the modified dimensions). Ignored if pdf == FALSE
+# pdf.overwrite: logical. Existing pdf can be overwritten? . Ignored if pdf == FALSE
+# rescale: kind of GUI. Either "R", "fit", or "fixed". Ignored on Mac and Linux OS. See ?windows for details
+# remove.read.only: logical. remove the read only (R.O.) graphical parameters? If TRUE, the graphical parameters are returned without the R.O. parameters. The returned $ini.par list can be used to set the par() of a new graphical device. If FALSE, graphical parameters are returned with the R.O. parameters, which provides information like text dimension (see ?par() ). The returned $ini.par list can be used to set the par() of a new graphical device, but generate a warning message. Ignored if return.output == FALSE. 
+# return.output: logical. Return output ? If TRUE the output list is displayed
+# RETURN
+# a list containing:
+# $pdf.loc: path of the pdf created
+# $ini.par: initial par() parameters
+# $zone.ini: initial window spliting
+# $dim: dimension of the graphical device (in inches)
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_open(pdf = FALSE, pdf.path = "C:/Users/Gael/Desktop", pdf.name = "graph", width = 7, height = 7, paper = "special", pdf.overwrite = FALSE, return.output = TRUE)
+# DEBUGGING
+# pdf = TRUE ; pdf.path = "C:/Users/Gael/Desktop" ; pdf.name = "graphs" ; width = 7 ; height = 7 ; paper = "special" ; pdf.overwrite = FALSE ; rescale = "fixed" ; remove.read.only = TRUE ; return.output = TRUE # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = pdf, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = pdf.path, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = pdf.name, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = height, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = paper, options = c("a4", "letter", "legal", "us", "executive", "a4r", "USr", "special", "A4", "LETTER", "LEGAL", "US"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data =pdf.overwrite, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = rescale, options = c("R", "fit", "fixed"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = remove.read.only, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.output, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if(pdf.path == "working.dir"){
+pdf.path <- getwd()
+}else{
+if(grepl(x = pdf.path, pattern = ".+/$")){
+pdf.path <- sub(x = pdf.path, pattern = "/$", replacement = "") # remove the last /
+}else if(grepl(x = pdf.path, pattern = ".+[\\]$")){ # or ".+\\\\$" # cannot be ".+\$" because \$ does not exist contrary to \n
+pdf.path <- sub(x = pdf.path, pattern = "[\\]$", replacement = "") # remove the last /
+}
+if(dir.exists(pdf.path) == FALSE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\npdf.path ARGUMENT DOES NOT CORRESPOND TO EXISTING DIRECTORY\n", pdf.path)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# par.ini recovery
+# cannot use pdf(file = NULL), because some small differences between pdf() and other devices. For instance, differences with windows() for par()$fin, par()$pin and par()$plt
+if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
+open.fail <- NULL
+grDevices::windows()
+ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+}else if(Sys.info()["sysname"] == "Linux"){
+if(pdf == TRUE){# cannot use pdf(file = NULL), because some small differences between pdf() and other devices. For instance, differences with windows() for par()$fin, par()$pin and par()$plt
+if(exists(".Random.seed", envir = .GlobalEnv)){ # if .Random.seed does not exists, it means that no random operation has been performed yet in any R environment
+tempo.random.seed <- .Random.seed
+on.exit(assign(".Random.seed", tempo.random.seed, env = .GlobalEnv))
+}else{
+on.exit(set.seed(NULL)) # inactivate seeding -> return to complete randomness
+}
+set.seed(NULL)
+tempo.code <- sample(x = 1:1e7, size = 1)
+while(file.exists(paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf")) == TRUE){
+tempo.code <- tempo.code + 1
+}
+grDevices::pdf(width = width, height = height, file=paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf"), paper = paper)
+ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the pdf window
+file.remove(paste0(pdf.path, "/recover_ini_par", tempo.code, ".pdf")) # remove the pdf file
+}else{
+# test if X11 can be opened
+if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHIS FUNCTION CANNOT BE USED ON LINUX IF A Rplots.pdf FILE ALREADY EXISTS HERE\n", getwd())
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+open.fail <- suppressWarnings(try(grDevices::X11(), silent = TRUE))[] # try to open a X11 window. If open.fail == NULL, no problem, meaning that the X11 window is opened. If open.fail != NULL, a pdf can be opened here paste0(getwd(), "/Rplots.pdf")
+if(is.null(open.fail)){
+ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+}else if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
+file.remove(paste0(getwd(), "/Rplots.pdf")) # remove the pdf file
+tempo.cat <- ("ERROR IN fun_open()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM\nTO OVERCOME THIS, EITHER SET THE X GRAPHIC INTERFACE OF THE SYSTEM OR SET THE pdf ARGUMENT OF THE fun_open() FUNCTION TO TRUE AND RERUN")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}
+}else{
+open.fail <- NULL
+grDevices::quartz()
+ini.par <- par(no.readonly = remove.read.only) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+}
+# end par.ini recovery 
+zone.ini <- matrix(1, ncol=1) # to recover the initial parameters for next figure region when device region split into several figure regions
+if(pdf == TRUE){
+if(grepl(x = pdf.name, pattern = "\\.pdf$")){
+pdf.name <- sub(x = pdf.name, pattern = "\\.pdf$", replacement = "") # remove the last .pdf
+}
+pdf.loc <- paste0(pdf.path, "/", pdf.name, ".pdf")
+if(file.exists(pdf.loc) == TRUE & pdf.overwrite == FALSE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\npdf.loc FILE ALREADY EXISTS AND CANNOT BE OVERWRITTEN DUE TO pdf.overwrite ARGUMENT SET TO TRUE\n", pdf.loc)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+grDevices::pdf(width = width, height = height, file=pdf.loc, paper = paper)
+}
+}else if(pdf == FALSE){
+pdf.loc <- NULL
+if(Sys.info()["sysname"] == "Windows"){ # .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
+grDevices::windows(width = width, height = height, rescale = rescale)
+}else if(Sys.info()["sysname"] == "Linux"){
+if( ! is.null(open.fail)){
+tempo.cat <- "ERROR IN fun_open()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM\nTO OVERCOME THIS, EITHER SET THE X GRAPHIC INTERFACE OF THE SYSTEM OR SET THE pdf ARGUMENT OF THE fun_open() FUNCTION TO TRUE AND RERUN"
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+grDevices::X11(width = width, height = height)
+}
+}else{
+grDevices::quartz(width = width, height = height)
+}
+}
+if(return.output == TRUE){
+output <- list(pdf.loc = pdf.loc, ini.par = ini.par, zone.ini = zone.ini, dim = dev.size())
+return(output)
+}
+}
+
+
+######## fun_prior_plot() #### set graph param before plotting (erase axes for instance)
+
+
+fun_prior_plot <- function(
+param.reinitial = FALSE, 
+xlog.scale = FALSE, 
+ylog.scale = FALSE, 
+remove.label = TRUE, 
+remove.x.axis = TRUE, 
+remove.y.axis = TRUE, 
+std.x.range = TRUE, 
+std.y.range = TRUE, 
+down.space = 1, 
+left.space = 1, 
+up.space = 1, 
+right.space = 1, 
+orient = 1, 
+dist.legend = 3.5, 
+tick.length = 0.5, 
+box.type = "n", 
+amplif.label = 1, 
+amplif.axis = 1, 
+display.extend = FALSE, 
+return.par = FALSE
+){
+# AIM
+# very convenient to erase the axes for post plot axis redrawing using fun_post_plot()
+# reinitialize and set the graphic parameters before plotting
+# CANNOT be used if no graphic device already opened
+# ARGUMENTS
+# param.reinitial: reinitialize graphic parameters before applying the new ones, as defined by the other arguments? Either TRUE or FALSE
+# xlog.scale: Log scale for the x-axis? Either TRUE or FALSE. If TRUE, erases the x-axis, except legend, for further drawing by fun_post_plot()(xlog argument of par())
+# ylog.scale: Log scale for the y-axis? Either TRUE or FALSE. If TRUE, erases the y-axis, except legend, for further drawing by fun_post_plot()(ylog argument of par())
+# remove.label: remove labels (axis legend) of the two axes? Either TRUE or FALSE (ann argument of par())
+# remove.x.axis: remove x-axis except legend? Either TRUE or FALSE (control the xaxt argument of par()). Automately set to TRUE if xlog.scale == TRUE
+# remove.y.axis: remove y-axis except legend? Either TRUE or FALSE (control the yaxt argument of par()). Automately set to TRUE if ylog.scale == TRUE
+# std.x.range: standard range on the x-axis? TRUE (no range extend) or FALSE (4% range extend). Controls xaxs argument of par() (TRUE is xaxs = "i", FALSE is xaxs = "r")
+# std.y.range: standard range on the y-axis? TRUE (no range extend) or FALSE (4% range extend). Controls yaxs argument of par() (TRUE is yaxs = "i", FALSE is yaxs = "r")
+# down.space: lower vertical margin (in inches, mai argument of par())
+# left.space: left horizontal margin (in inches, mai argument of par())
+# up.space: upper vertical margin between plot region and grapical window (in inches, mai argument of par())
+# right.space: right horizontal margin (in inches, mai argument of par())
+# orient: scale number orientation (las argument of par()). 0, always parallel to the axis; 1, always horizontal; 2, always perpendicular to the axis; 3, always vertical
+# dist.legend: numeric value that moves axis legends away in inches (first number of mgp argument of par() but in inches thus / 0.2)
+# tick.length: length of the ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc. 0 means no tick
+# box.type: bty argument of par(). Either "o", "l", "7", "c", "u", "]", the resulting box resembles the corresponding upper case letter. A value of "n" suppresses the box
+# amplif.label: increase or decrease the size of the text in legends
+# amplif.axis: increase or decrease the size of the scale numbers in axis
+# display.extend: extend display beyond plotting region? Either TRUE or FALSE (xpd argument of par() without NA)
+# return.par: return graphic parameter modification?
+# RETURN
+# return graphic parameter modification
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_prior_plot(param.reinitial = FALSE, xlog.scale = FALSE, ylog.scale = FALSE, remove.label = TRUE, remove.x.axis = TRUE, remove.y.axis = TRUE, std.x.range = TRUE, std.y.range = TRUE, down.space = 1, left.space = 1, up.space = 1, right.space = 1, orient = 1, dist.legend = 4.5, tick.length = 0.5, box.type = "n", amplif.label = 1, amplif.axis = 1, display.extend = FALSE, return.par = FALSE)
+# DEBUGGING
+# param.reinitial = FALSE ; xlog.scale = FALSE ; ylog.scale = FALSE ; remove.label = TRUE ; remove.x.axis = TRUE ; remove.y.axis = TRUE ; std.x.range = TRUE ; std.y.range = TRUE ; down.space = 1 ; left.space = 1 ; up.space = 1 ; right.space = 1 ; orient = 1 ; dist.legend = 4.5 ; tick.length = 0.5 ; box.type = "n" ; amplif.label = 1 ; amplif.axis = 1 ; display.extend = FALSE ; return.par = FALSE # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = param.reinitial, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = xlog.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = ylog.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = remove.label, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = remove.x.axis, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = remove.y.axis, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = std.x.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = std.y.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = down.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = up.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = orient, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.type, options = c("o", "l", "7", "c", "u", "]", "n"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = amplif.label, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = amplif.axis, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = display.extend, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.par, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if(is.null(dev.list())){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THIS FUNCTION CANNOT BE USED IF NO GRAPHIC DEVICE ALREADY OPENED (dev.list() IS CURRENTLY NULL)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# par.ini recovery
+# cannot use pdf(file = NULL), because some small differences between pdf() and other devices. For instance, differences with windows() for par()$fin, par()$pin and par()$plt
+if(param.reinitial == TRUE){
+if( ! all(names(dev.cur()) == "null device")){
+active.wind.nb <- dev.cur()
+}else{
+active.wind.nb <- 0
+}
+if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
+grDevices::windows()
+ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+}else if(Sys.info()["sysname"] == "Linux"){
+if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THIS FUNCTION CANNOT BE USED ON LINUX WITH param.reinitial SET TO TRUE IF A Rplots.pdf FILE ALREADY EXISTS HERE: ", getwd())
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+open.fail <- suppressWarnings(try(grDevices::X11(), silent = TRUE))[] # try to open a X11 window. If open.fail == NULL, no problem, meaning that the X11 window is opened. If open.fail != NULL, a pdf can be opened here paste0(getwd(), "/Rplots.pdf")
+if(is.null(open.fail)){
+ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+}else if(file.exists(paste0(getwd(), "/Rplots.pdf"))){
+ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+invisible(dev.off()) # close the new window
+file.remove(paste0(getwd(), "/Rplots.pdf")) # remove the pdf file
+}else{
+tempo.cat <- ("ERROR IN fun_prior_plot()\nTHIS FUNCTION CANNOT OPEN GUI ON LINUX OR NON MACOS UNIX SYSTEM\nTO OVERCOME THIS, PLEASE USE A PDF GRAPHIC INTERFACE AND RERUN")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}else{ # macOS
+grDevices::quartz()
+ini.par <- par(no.readonly = FALSE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened)
+invisible(dev.off()) # close the new window
+}
+if( ! all(names(dev.cur()) == "null device")){
+invisible(dev.set(active.wind.nb)) # go back to the active window if exists
+par(ini.par) # apply the initial par to current window
+}
+}
+# end par.ini recovery
+if(remove.x.axis == TRUE){
+par(xaxt = "n") # suppress the y-axis label
+}else{
+par(xaxt = "s")
+}
+if(remove.y.axis == TRUE){
+par(yaxt = "n") # suppress the y-axis label
+}else{
+par(yaxt = "s")
+}
+if(std.x.range == TRUE){
+par(xaxs = "i")
+}else{
+par(xaxs = "r")
+}
+if(std.y.range == TRUE){
+par(yaxs = "i")
+}else{
+par(yaxs = "r")
+}
+par(mai = c(down.space, left.space, up.space, right.space), ann = ! remove.label, las = orient, mgp = c(dist.legend/0.2, 1, 0), xpd = display.extend, bty= box.type, cex.lab = amplif.label, cex.axis = amplif.axis)
+par(tcl = -par()$mgp[2] * tick.length) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
+if(xlog.scale == TRUE){
+par(xaxt = "n", xlog = TRUE) # suppress the x-axis label
+}else{
+par(xlog = FALSE)
+}
+if(ylog.scale == TRUE){
+par(yaxt = "n", ylog = TRUE) # suppress the y-axis label
+}else{
+par(ylog = FALSE)
+}
+if(return.par == TRUE){
+tempo.par <- par()
+return(tempo.par)
+}
+}
+
+
+######## fun_scale() #### select nice label numbers when setting number of ticks on an axis
+
+
+ 
+
+
+fun_scale <- function(n, lim, kind = "approx", lib.path = NULL){
+# AIM
+# attempt to select nice scale numbers when setting n ticks on a lim axis range
+# ARGUMENTS
+# n: desired number of main ticks on the axis (integer above 0)
+# lim: vector of 2 numbers indicating the limit range of the axis. Order of the 2 values matters (for inverted axis). Can be log transformed values
+# kind: either "approx" (approximative), "strict" (strict) or "strict.cl" (strict clean). If "approx", use the scales::trans_breaks() function to provide an easy to read scale of approximately n ticks spanning the range of the lim argument. If "strict", cut the range of the lim argument into n + 1 equidistant part and return the n numbers at each boundary. This often generates numbers uneasy to read. If "strict.cl", provide an easy to read scale of exactly n ticks, but sometimes not completely spanning the range of the lim argument
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# RETURN
+# a vector of numbers
+# REQUIRED PACKAGES
+# if kind = "approx":
+# ggplot2
+# scales
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_round()
+# EXAMPLES
+# approximate number of main ticks
+# ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "approx") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
+# strict number of main ticks
+# ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "strict") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
+# strict "clean" number of main ticks
+# ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "strict.cl") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
+# approximate number of main ticks, scale inversion
+# ymin = 3.101 ; ymax = 2 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "approx") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
+# DEBUGGING
+# n = 9 ; lim = c(2, 3.101) ; kind = "approx" ; lib.path = NULL # for function debugging
+# n = 10 ; lim = c(1e-4, 1e6) ; kind = "approx" ; lib.path = NULL # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# end initial argument checking
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_round", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_round() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & isTRUE(all.equal(n, 0))){ # isTRUE(all.equal(n, 0)) equivalent to n == 0 but deals with floats (approx ok)
+tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A NON NULL AND POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE) # 
+}
+tempo <- fun_check(data = lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & all(diff(lim) == 0L)){ # isTRUE(all.equal(diff(lim), rep(0, length(diff(lim))))) not used because we strictly need zero as a result
+tempo.cat <- paste0("ERROR IN ", function.name, ": lim ARGUMENT HAS A NULL RANGE (2 IDENTICAL VALUES)")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & any(lim %in% c(Inf, -Inf))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = kind, options = c("approx", "strict", "strict.cl"), length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+lim.rank <- rank(lim) # to deal with inverted axis
+lim <- sort(lim)
+if(kind == "approx"){
+# package checking
+fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
+fun_pack(req.package = c("scales"), lib.path = lib.path)
+# end package checking
+output <- ggplot2::ggplot_build(ggplot2::ggplot() + ggplot2::scale_y_continuous(
+breaks = scales::trans_breaks(
+trans = "identity", 
+inv = "identity", 
+n = n
+), 
+limits = lim
+))$layout$panel_params[[1]]$y$breaks # pretty() alone is not appropriate: tempo.pret <-  pretty(seq(lim[1] ,lim[2], length.out = n)) ; tempo.pret[tempo.pret > = lim[1] & tempo.pret < = lim[2]]. # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks
+if( ! is.null(attributes(output))){ # layout$panel_params[[1]]$y$breaks can be characters (labels of the axis). In that case, it has attributes that corresponds to positions
+output <- unlist(attributes(output))
+}
+output <- output[ ! is.na(output)]
+}else if(kind == "strict"){
+output <- fun_round(seq(lim[1] ,lim[2], length.out = n), 2)
+}else if(kind == "strict.cl"){
+tempo.range <- diff(sort(lim))
+tempo.max <- max(lim)
+tempo.min <- min(lim)
+mid <- tempo.min + (tempo.range/2) # middle of axis
+tempo.inter <- tempo.range / (n + 1) # current interval between two ticks, between 0 and Inf
+if(tempo.inter == 0L){ # isTRUE(all.equal(tempo.inter, rep(0, length(tempo.inter)))) not used because we strictly need zero as a result
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE INTERVAL BETWEEN TWO TICKS OF THE SCALE IS NULL. MODIFY THE lim OR n ARGUMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+log10.abs.lim <- 200
+log10.range <- (-log10.abs.lim):log10.abs.lim
+log10.vec <- 10^log10.range
+round.vec <- c(5, 4, 3, 2.5, 2, 1.25, 1)
+dec.table <- outer(log10.vec, round.vec) # table containing the scale units (row: power of ten from -201 to +199, column: the 5, 2.5, 2, 1.25, 1 notches
+
+ 
+
+# recover the number of leading zeros in tempo.inter
+ini.scipen <- options()$scipen
+options(scipen = -1000) # force scientific format
+if(any(grepl(pattern = "\\+", x = tempo.inter))){ # tempo.inter > 1
+power10.exp <- as.integer(substring(text = tempo.inter, first = (regexpr(pattern = "\\+", text = tempo.inter) + 1))) # recover the power of 10. Example recover 08 from 1e+08
+mantisse <- as.numeric(substr(x = tempo.inter, start = 1, stop = (regexpr(pattern = "\\+", text = tempo.inter) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
+}else if(any(grepl(pattern = "\\-", x = tempo.inter))){ # tempo.inter < 1
+power10.exp <- as.integer(substring(text = tempo.inter, first = (regexpr(pattern = "\\-", text = tempo.inter)))) # recover the power of 10. Example recover 08 from 1e+08
+mantisse <- as.numeric(substr(x = tempo.inter, start = 1, stop = (regexpr(pattern = "\\-", text = tempo.inter) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+tempo.scale <- dec.table[log10.range == power10.exp, ]
+# new interval 
+inter.select <- NULL
+for(i1 in 1:length(tempo.scale)){
+tempo.first.tick <- trunc((tempo.min + tempo.scale[i1]) / tempo.scale[i1]) * (tempo.scale[i1]) # this would be use to have a number not multiple of tempo.scale[i1]: ceiling(tempo.min) + tempo.scale[i1] * 10^power10.exp
+tempo.last.tick <- tempo.first.tick + tempo.scale[i1] * (n - 1)
+if((tempo.first.tick >= tempo.min) & (tempo.last.tick <= tempo.max)){
+inter.select <- tempo.scale[i1]
+break()
+}
+}
+if(is.null(inter.select)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+options(scipen = ini.scipen) # restore the initial scientific penalty
+# end new interval 
+# centering the new scale 
+tempo.mid <- trunc((mid + (-1:1) * inter.select) / inter.select) * inter.select # tempo middle tick closest to the middle axis
+mid.tick <- tempo.mid[which.min(abs(tempo.mid - mid))]
+if(isTRUE(all.equal(n, rep(1, length(n))))){ # isTRUE(all.equal(n, rep(1, length(n)))) is similar to n == 1L but deals with float
+output <- mid.tick
+}else if(isTRUE(all.equal(n, rep(2, length(n))))){ # isTRUE(all.equal(n, rep(0, length(n)))) is similar to n == 2L but deals with float
+output <- mid.tick
+tempo.min.dist <- mid.tick - inter.select - tempo.min
+tempo.max.dist <- tempo.max - mid.tick + inter.select
+if(tempo.min.dist <= tempo.max.dist){ # distance between lowest tick and bottom axis <= distance between highest tick and top axis. If yes, extra tick but at the top, otherwise at the bottom
+output <- c(mid.tick, mid.tick + inter.select)
+}else{
+output <- c(mid.tick - inter.select, mid.tick)
+}
+}else if((n / 2 - trunc(n / 2)) > 0.1){ # > 0.1 to avoid floating point. Because result can only be 0 or 0.5. Thus, > 0.1 means odd number
+output <- c(mid.tick - (trunc(n / 2):1) * inter.select, mid.tick, mid.tick + (1:trunc(n / 2)) * inter.select)
+}else if((n / 2 - trunc(n / 2)) < 0.1){ # < 0.1 to avoid floating point. Because result can only be 0 or 0.5. Thus, < 0.1 means even number
+tempo.min.dist <- mid.tick - trunc(n / 2) * inter.select - tempo.min
+tempo.max.dist <- tempo.max - mid.tick + trunc(n / 2) * inter.select
+if(tempo.min.dist <= tempo.max.dist){ # distance between lowest tick and bottom axis <= distance between highest tick and top axis. If yes, extra tick but at the bottom, otherwise at the top
+output <- c(mid.tick - ((trunc(n / 2) - 1):1) * inter.select, mid.tick, mid.tick + (1:trunc(n / 2)) * inter.select)
+}else{
+output <- c(mid.tick - (trunc(n / 2):1) * inter.select, mid.tick, mid.tick + (1:(trunc(n / 2) - 1)) * inter.select)
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end centering the new scale 
+# last check
+if(min(output) < tempo.min){
+output <- c(output[-1], max(output) + inter.select) # remove the lowest tick and add a tick at the top
+}else if( max(output) > tempo.max){
+output <- c(min(output) - inter.select, output[-length(output)])
+}
+if(min(output) < tempo.min | max(output) > tempo.max){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(is.na(output))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5 (NA GENERATION)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end last check
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 6")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(diff(lim.rank) < 0){
+output <- rev(output)
+}
+return(output)
+}
+
+
+######## fun_inter_ticks() #### define coordinates of secondary ticks
+
+
+fun_inter_ticks <- function(
+lim, 
+log = "log10", 
+breaks = NULL, 
+n = NULL, 
+warn.print = TRUE
+){
+# AIM
+# define coordinates and values of secondary ticks
+# ARGUMENTS
+# lim: vector of 2 numbers indicating the limit range of the axis. Order of the 2 values matters (for inverted axis). If log argument is "log2" or "log10", values in lim must be already log transformed. Thus, negative or zero values are allowed
+# log: either "log2" (values in the lim argument are log2 transformed) or "log10" (values in the lim argument are log10 transformed), or "no"
+# breaks: mandatory vector of numbers indicating the main ticks values/positions when log argument is "no". Ignored when log argument is "log2" or "log10"
+# n: number of secondary ticks between each main tick when log argument is "no". Ignored when log argument is "log2" or "log10"
+# warn.print: logical. Print potential warning messages at the end of the execution? If FALSE, warning messages are never printed, but can still be recovered in the returned list
+# RETURN
+# a list containing
+# $log: value of the log argument used
+# $coordinates: the coordinates of the secondary ticks on the axis, between the lim values
+# $values: the corresponding values associated to each coordinate (with log scale, 2^$values or 10^$values is equivalent to the labels of the axis)
+# $warn: the potential warning messages. Use cat() for proper display. NULL if no warning
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# no log scale
+# fun_inter_ticks(lim = c(-4,4), log = "no", breaks = c(-2, 0, 2), n = 3)
+# fun_inter_ticks(lim = c(10, 0), log = "no", breaks = c(10, 8, 6, 4, 2, 0), n = 4)
+# log2
+# fun_inter_ticks(lim = c(-4,4), log = "log2")
+# log10
+# fun_inter_ticks(lim = c(-2,3), log = "log10")
+# DEBUGGING
+# lim = c(2, 3.101) ; log = "no" ; breaks = NULL ; n = NULL ; warn.print = TRUE # for function debugging
+# lim = c(0, 26.5) ; log = "no" ; breaks = c(0, 10, 20) ; n = 3 # for function debugging
+# lim = c(10, 0); log = "no"; breaks = c(10, 8, 6, 4, 2, 0); n = 4 # for function debugging
+# lim = c(-10, -20); log = "no"; breaks = c(-20, -15, -10); n = 4 # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+req.function <- c(
+"fun_check"
+)
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED ", i1, "() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end required function checking
+# argument primary checking
+# arg with no default values
+mandat.args <- c(
+"lim"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# using fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(breaks)){
+tempo <- fun_check(data = breaks, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(n)){
+tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = warn.print, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA
+if(any(is.na(lim)) | any(is.na(log)) | any(is.na(breaks)) | any(is.na(n)) | any(is.na(warn.print))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nNO ARGUMENT CAN HAVE NA VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA
+# management of NULL
+if(is.null(lim) | is.null(log)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHESE ARGUMENTS\nlim\nlog\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL
+if(all(diff(lim) == 0L)){ # isTRUE(all.equal(diff(lim), rep(0, length(diff(lim))))) not used because we strictly need zero as a result
+tempo.cat <- paste0("ERROR IN ", function.name, "\nlim ARGUMENT HAS A NULL RANGE (2 IDENTICAL VALUES): ", paste(lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(any(lim %in% c(Inf, -Inf))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nlim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(log == "no" & is.null(breaks)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT CANNOT BE NULL IF log ARGUMENT IS \"no\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(breaks)){
+if(length(breaks) < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT MUST HAVE 2 VALUES AT LEAST (OTHERWISE, INTER TICK POSITIONS CANNOT BE COMPUTED): ", paste(breaks, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! isTRUE(all.equal(diff(sort(breaks)), rep(diff(sort(breaks))[1], length(diff(sort(breaks))))))){ # isTRUE(all.equal(n, 0)) equivalent to n == 0 but deals with floats (approx ok)
+tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT MUST HAVE EQUIDISTANT VALUES (OTHERWISE, EQUAL NUMBER OF INTER TICK BETWEEN MAIN TICKS CANNOT BE COMPUTED): ", paste(breaks, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if( ! is.null(n)){
+if(n <= 0){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nn ARGUMENT MUST BE A POSITIVE AND NON NULL INTEGER: ", paste(n, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end second round of checking and data preparation
+# main code
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+lim.rank <- rank(lim) # to deal with inverse axis
+if(log != "no"){
+ini.scipen <- options()$scipen
+options(scipen = -1000) # force scientific format
+power10.exp <- as.integer(substring(text = 10^lim, first = (regexpr(pattern = "\\+|\\-", text = 10^lim)))) # recover the power of 10, i.e., integer part of lim. Example recover 08 from 1e+08. Works for log2
+# mantisse <- as.numeric(substr(x = 10^lim, start = 1, stop = (regexpr(pattern = "\\+|\\-", text = 10^lim) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
+options(scipen = ini.scipen) # restore the initial scientific penalty
+tick.pos <- unique(as.vector(outer(2:10, ifelse(log == "log2", 2, 10)^((power10.exp[1] - ifelse(diff(lim.rank) > 0, 1, -1)):(power10.exp[2] + ifelse(diff(lim.rank) > 0, 1, -1)))))) # use log10(2:10) even if log2: it is to get log values between 0 and 1
+tick.pos <- sort(tick.pos, decreasing = ifelse(diff(lim.rank) > 0, FALSE, TRUE))
+if(log == "log2"){
+tick.values <- tick.pos[tick.pos >= min(2^lim) & tick.pos <= max(2^lim)]
+tick.pos <- log2(tick.values)
+}else if(log == "log10"){
+tick.values <- tick.pos[tick.pos >= min(10^lim) & tick.pos <= max(10^lim)]
+tick.pos <- log10(tick.values)
+}
+}else{
+# if(length(breaks) > 1){ # not required because already checked above
+breaks.rank <- rank(c(breaks[1], breaks[length(breaks)]))
+if(diff(breaks.rank) != diff(lim.rank)){
+breaks <- sort(breaks, decreasing = ifelse(diff(lim.rank) < 0, TRUE, FALSE))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") VALUES IN breaks ARGUMENT NOT IN THE SAME ORDER AS IN lim ARGUMENT -> VALUES REORDERED AS IN lim: ", paste(breaks, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+breaks.rank <- rank(c(breaks[1], breaks[length(breaks)]))
+}
+# }
+main.tick.dist <- mean(diff(breaks), na.rm = TRUE)
+tick.dist <- main.tick.dist / (n + 1)
+tempo.extra.margin <- max(abs(diff(breaks)), na.rm = TRUE)
+tick.pos <- seq(
+if(diff(breaks.rank) > 0){breaks[1] - tempo.extra.margin}else{breaks[1] + tempo.extra.margin}, 
+if(diff(breaks.rank) > 0){breaks[length(breaks)] + tempo.extra.margin}else{breaks[length(breaks)] - tempo.extra.margin}, 
+by = tick.dist
+)
+tick.pos <- tick.pos[tick.pos >= min(lim) & tick.pos <= max(lim)]
+tick.values <- tick.pos
+}
+if(any(is.na(tick.pos) | ! is.finite(tick.pos))){ 
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, ": NA or Inf GENERATED FOR THE INTER TICK POSITIONS: ", paste(tick.pos, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(tick.pos) == 0L){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO INTER TICKS COMPUTED BETWEEN THE LIMITS INDICATED: ", paste(lim, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+output <- list(log = log, coordinates = tick.pos, values = tick.values, warn = warn)
+if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE)) # to recover the warning messages, see $warn
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+return(output)
+}
+
+
+######## fun_post_plot() #### set graph param after plotting (axes redesign for instance)
+
+
+ 
+
+
+fun_post_plot <- function(
+x.side = 0, 
+x.log.scale = FALSE, 
+x.categ = NULL, 
+x.categ.pos = NULL, 
+x.lab = "", 
+x.axis.size = 1.5, 
+x.label.size = 1.5, 
+x.dist.legend = 0.5, 
+x.nb.inter.tick = 1, 
+y.side = 0, 
+y.log.scale = FALSE, 
+y.categ = NULL, 
+y.categ.pos = NULL, 
+y.lab = "", 
+y.axis.size = 1.5, 
+y.label.size = 1.5, 
+y.dist.legend = 0.5, 
+y.nb.inter.tick = 1, 
+text.angle = 90, 
+tick.length = 0.5, 
+sec.tick.length = 0.3, 
+bg.color = NULL, 
+grid.lwd = NULL, 
+grid.col = "white", 
+corner.text = "", 
+corner.text.size = 1, 
+just.label.add = FALSE, 
+par.reset = FALSE, 
+custom.par = NULL
+){
+# AIM
+# redesign axis. If x.side = 0, y.side = 0, the function just adds text at topright of the graph and reset par() for next graphics and provides outputs (see below)
+# provide also positions for legend or additional text on the graph
+# use fun_prior_plot() before this function for initial inactivation of the axis drawings
+# ARGUMENTS
+# x.side: axis at the bottom (1) or top (3) of the region figure. Write 0 for no change
+# x.log.scale: Log scale for the x-axis? Either TRUE or FALSE
+# x.categ: character vector representing the classes (levels()) to specify when the x-axis is qualititative(stripchart, boxplot)
+# x.categ.pos: position of the classes names (numeric vector of identical length than x.categ). If left NULL, this will be 1:length(levels())
+# x.lab: label of the x-axis. If x.side == 0 and x.lab != "", then x.lab is printed
+# x.axis.size: positive numeric. Increase or decrease the size of the x axis numbers. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2. Also control the size of displayed categories
+# x.label.size: positive numeric. Increase or decrease the size of the x axis legend text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
+# x.dist.legend: increase the number to move x-axis legends away in inches (first number of mgp argument of par() but in inches)
+# x.nb.inter.tick: number of secondary ticks between main ticks on x-axis (only if not log scale). 0 means no secondary ticks
+# y.side: axis at the left (2) or right (4) of the region figure. Write 0 for no change
+# y.log.scale: Log scale for the y-axis? Either TRUE or FALSE
+# y.categ: classes (levels()) to specify when the y-axis is qualititative(stripchart, boxplot)
+# y.categ.pos: position of the classes names (numeric vector of identical length than y.categ). If left NULL, this will be 1:length(levels())
+# y.lab: label of the y-axis. If y.side == 0 and y.lab != "", then y.lab is printed
+# y.axis.size: positive numeric. Increase or decrease the size of the y axis numbers. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2. Also control the size of displayed categories
+# y.label.size: positive numeric. Increase or decrease the size of the y axis legend text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
+# y.dist.legend: increase the number to move y-axis legends away in inches (first number of mgp argument of par() but in inches)
+# y.nb.inter.tick: number of secondary ticks between main ticks on y-axis (only if not log scale). 0 means non secondary ticks
+# text.angle: angle of the text when axis is qualitative
+# tick.length: length of the main ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
+# sec.tick.length: length of the secondary ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
+# bg.color: background color of the plot region. NULL for no color. BEWARE: cover/hide an existing plot !
+# grid.lwd: if non NULL, activate the grid line (specify the line width)
+# grid.col: grid line color (only if grid.lwd non NULL)
+# corner.text: text to add at the top right corner of the window
+# corner.text.size: positive numeric. Increase or decrease the size of the text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
+# par.reset: to reset all the graphics parameters. BEWARE: TRUE can generate display problems, mainly in graphic devices with multiple figure regions
+# just.label.add: just add axis labels (legend)? Either TRUE or FALSE. If TRUE, at least (x.side == 0 & x.lab != "") or (y.side == 0 & y.lab != "") must be set to display the corresponding x.lab or y.lab
+# custom.par: list that provides the parameters that reset all the graphics parameters. BEWARE: if NULL and par.reset == TRUE, the default par() parameters are used
+# RETURN
+# a list containing: 
+# $x.mid.left.dev.region: middle of the left margin of the device region, in coordinates of the x-axis
+# $x.left.dev.region: left side of the left margin (including the potential margin of the device region), in coordinates of the x-axis
+# $x.mid.right.dev.region: middle of the right margin of the device region, in coordinates of the x-axis
+# $x.right.dev.region: right side of the right margin (including the potential margin of the device region), in coordinates of the x-axis
+# $x.mid.left.fig.region: middle of the left margin of the figure region, in coordinates of the x-axis
+# $x.left.fig.region: left side of the left margin, in coordinates of the x-axis
+# $x.mid.right.fig.region: middle of the right margin of the figure region, in coordinates of the x-axis
+# $x.right.fig.region: right side of the right margin, in coordinates of the x-axis
+# $x.left.plot.region: left side of the plot region, in coordinates of the x-axis
+# $x.right.plot.region: right side of the plot region, in coordinates of the x-axis
+# $x.mid.plot.region: middle of the plot region, in coordinates of the x-axis
+# $y.mid.bottom.dev.region: middle of the bottom margin of the device region, in coordinates of the y-axis
+# $y.bottom.dev.region: bottom side of the bottom margin (including the potential margin of the device region), in coordinates of the y-axis
+# $y.mid.top.dev.region: middle of the top margin of the device region, in coordinates of the y-axis
+# $y.top.dev.region: top side of the top margin (including the potential margin of the device region), in coordinates of the y-axis
+# $y.mid.bottom.fig.region: middle of the bottom margin of the figure region, in coordinates of the y-axis
+# $y.bottom.fig.region: bottom of the bottom margin of the figure region, in coordinates of the y-axis
+# $y.mid.top.fig.region: middle of the top margin of the figure region, in coordinates of the y-axis
+# $y.top.fig.region: top of the top margin of the figure region, in coordinates of the y-axis
+# $y.top.plot.region: top of the plot region, in coordinates of the y-axis
+# $y.bottom.plot.region: bottom of the plot region, in coordinates of the y-axis
+# $y.mid.plot.region: middle of the plot region, in coordinates of the y-axis
+# $text: warning text
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_open() to reinitialize graph parameters if par.reset = TRUE and custom.par = NULL
+# EXAMPLES
+# Example of log axis with log y-axis and unmodified x-axis:
+# prior.par <- fun_prior_plot(param.reinitial = TRUE, xlog.scale = FALSE, ylog.scale = TRUE, remove.label = TRUE, remove.x.axis = FALSE, remove.y.axis = TRUE, down.space = 1, left.space = 1, up.space = 1, right.space = 1, orient = 1, dist.legend = 0.5, tick.length = 0.5, box.type = "n", amplif.label = 1, amplif.axis = 1, display.extend = FALSE, return.par = TRUE) ; plot(1:100, log = "y") ; fun_post_plot(y.side = 2, y.log.scale = prior.par$ylog, x.lab = "Values", y.lab = "TEST", y.axis.size = 1.25, y.label.size = 1.5, y.dist.legend = 0.7, just.label.add = ! prior.par$ann)
+# Example of log axis with redrawn x-axis and y-axis:
+# prior.par <- fun_prior_plot(param.reinitial = TRUE) ; plot(1:100) ; fun_post_plot(x.side = 1, x.lab = "Values", y.side = 2, y.lab = "TEST", y.axis.size = 1, y.label.size = 2, y.dist.legend = 0.6)
+# Example of title easily added to a plot:
+# plot(1:100) ; para <- fun_post_plot(corner.text = "TITLE ADDED") # try also: par(xpd = TRUE) ; text(x = para$x.mid.left.fig.region, y = para$y.mid.top.fig.region, labels = "TITLE ADDED", cex = 0.5)
+# example with margins in the device region:
+# windows(5,5) ; fun_prior_plot(box.type = "o") ; par(mai=c(0.5,0.5,0.5,0.5), omi = c(0.25,0.25,1,0.25), xaxs = "i", yaxs = "i") ; plot(0:10) ; a <- fun_post_plot(x.side = 0, y.side = 0) ; x <- c(a$x.mid.left.dev.region, a$x.left.dev.region, a$x.mid.right.dev.region, a$x.right.dev.region, a$x.mid.left.fig.region, a$x.left.fig.region, a$x.mid.right.fig.region, a$x.right.fig.region, a$x.right.plot.region, a$x.left.plot.region, a$x.mid.plot.region) ; y <- c(a$y.mid.bottom.dev.region, a$y.bottom.dev.region, a$y.mid.top.dev.region, a$y.top.dev.region, a$y.mid.bottom.fig.region, a$y.bottom.fig.region, a$y.mid.top.fig.region, a$y.top.fig.region, a$y.top.plot.region, a$y.bottom.plot.region, a$y.mid.plot.region) ; par(xpd = NA) ; points(x = rep(5, length(y)), y = y, pch = 16, col = "red") ; text(x = rep(5, length(y)), y = y, c("y.mid.bottom.dev.region", "y.bottom.dev.region", "y.mid.top.dev.region", "y.top.dev.region", "y.mid.bottom.fig.region", "y.bottom.fig.region", "y.mid.top.fig.region", "y.top.fig.region", "y.top.plot.region", "y.bottom.plot.region", "y.mid.plot.region"), cex = 0.65, col = grey(0.25)) ; points(y = rep(5, length(x)), x = x, pch = 16, col = "blue") ; text(y = rep(5, length(x)), x = x, c("x.mid.left.dev.region", "x.left.dev.region", "x.mid.right.dev.region", "x.right.dev.region", "x.mid.left.fig.region", "x.left.fig.region", "x.mid.right.fig.region", "x.right.fig.region", "x.right.plot.region", "x.left.plot.region", "x.mid.plot.region"), cex = 0.65, srt = 90, col = grey(0.25))
+# DEBUGGING
+# x.side = 0 ; x.log.scale = FALSE ; x.categ = NULL ; x.categ.pos = NULL ; x.lab = "" ; x.axis.size = 1.5 ; x.label.size = 1.5 ; x.dist.legend = 1 ; x.nb.inter.tick = 1 ; y.side = 0 ; y.log.scale = FALSE ; y.categ = NULL ; y.categ.pos = NULL ; y.lab = "" ; y.axis.size = 1.5 ; y.label.size = 1.5 ; y.dist.legend = 0.7 ; y.nb.inter.tick = 1 ; text.angle = 90 ; tick.length = 0.5 ; sec.tick.length = 0.3 ; bg.color = NULL ; grid.lwd = NULL ; grid.col = "white" ; corner.text = "" ; corner.text.size = 1 ; just.label.add = FALSE ; par.reset = FALSE ; custom.par = NULL # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_open", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_open() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = x.side, options = c(0, 1, 3), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.log.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(x.categ)){
+tempo <- fun_check(data = x.categ, class = "character", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(x.categ.pos)){
+tempo <- fun_check(data = x.categ.pos, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = x.lab, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.axis.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.label.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.nb.inter.tick, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.side, options = c(0, 2, 4), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.log.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(y.categ)){
+tempo <- fun_check(data = y.categ, class = "character", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(y.categ.pos)){
+tempo <- fun_check(data = y.categ.pos, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = y.lab, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.axis.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.label.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.nb.inter.tick, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = text.angle, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = sec.tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+if( ! is.null(bg.color)){
+tempo <- fun_check(data = bg.color, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if( ! (bg.color %in% colors() | grepl(pattern = "^#", bg.color))){ # check color
+tempo.cat <- paste0("ERROR IN ", function.name, ": bg.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # OR A COLOR NAME GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+if( ! is.null(grid.lwd)){
+tempo <- fun_check(data = grid.lwd, class = "vector", mode = "numeric", neg.values = FALSE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(grid.col)){
+tempo <- fun_check(data = grid.col, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if( ! (grid.col %in% colors() | grepl(pattern = "^#", grid.col))){ # check color
+tempo.cat <- paste0("ERROR IN ", function.name, ": grid.col ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # OR A COLOR NAME GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = corner.text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = corner.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = just.label.add, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = par.reset, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(custom.par)){
+tempo <- fun_check(data = custom.par, typeof = "list", length = 1, fun.name = function.name) ; eval(ee)
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+text <- NULL
+par(tcl = -par()$mgp[2] * tick.length)
+if(x.log.scale == TRUE){
+grid.coord.x <- c(10^par("usr")[1], 10^par("usr")[2])
+}else{
+grid.coord.x <- c(par("usr")[1], par("usr")[2])
+}
+if(y.log.scale == TRUE){
+grid.coord.y <- c(10^par("usr")[3], 10^par("usr")[4])
+}else{
+grid.coord.y <- c(par("usr")[3], par("usr")[4])
+}
+if( ! is.null(bg.color)){
+rect(grid.coord.x[1], grid.coord.y[1], grid.coord.x[2], grid.coord.y[2], col = bg.color, border = NA)
+}
+if( ! is.null(grid.lwd)){
+grid(nx = NA, ny = NULL, col = grid.col, lty = 1, lwd = grid.lwd)
+}
+if(x.log.scale == TRUE){
+x.mid.left.dev.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
+x.left.dev.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1]) # in x coordinates
+x.mid.right.dev.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
+x.right.dev.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2])) # in x coordinates
+x.mid.left.fig.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
+x.left.fig.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1]) # in x coordinates
+x.mid.right.fig.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
+x.right.fig.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2])) # in x coordinates
+x.left.plot.region <- 10^par("usr")[1] # in x coordinates, left of the plot region (according to x scale)
+x.right.plot.region <- 10^par("usr")[2] # in x coordinates, right of the plot region (according to x scale)
+x.mid.plot.region <- 10^((par("usr")[2] + par("usr")[1]) / 2) # in x coordinates, right of the plot region (according to x scale)
+}else{
+x.mid.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
+x.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1]) # in x coordinates
+x.mid.right.dev.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
+x.right.dev.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2])) # in x coordinates
+x.mid.left.fig.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
+x.left.fig.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1]) # in x coordinates
+x.mid.right.fig.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
+x.right.fig.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2])) # in x coordinates
+x.left.plot.region <- par("usr")[1] # in x coordinates, left of the plot region (according to x scale)
+x.right.plot.region <- par("usr")[2] # in x coordinates, right of the plot region (according to x scale)
+x.mid.plot.region <- (par("usr")[2] + par("usr")[1]) / 2 # in x coordinates, right of the plot region (according to x scale)
+}
+if(y.log.scale == TRUE){
+y.mid.bottom.dev.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (par("omd")[3] / 2)) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
+y.bottom.dev.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * par("omd")[3]) # in y coordinates
+y.mid.top.dev.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
+y.top.dev.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4])) # in y coordinates
+y.mid.bottom.fig.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] / 2) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
+y.bottom.fig.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3]) # in y coordinates
+y.mid.top.fig.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
+y.top.fig.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4])) # in y coordinates
+y.top.plot.region <- 10^par("usr")[4] # in y coordinates, top of the plot region (according to y scale)
+y.bottom.plot.region <- 10^par("usr")[3] # in y coordinates, bottom of the plot region (according to y scale)
+y.mid.plot.region <- (par("usr")[3] + par("usr")[4]) / 2 # in x coordinates, right of the plot region (according to x scale)
+}else{
+y.mid.bottom.dev.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (par("omd")[3] / 2)) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
+y.bottom.dev.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * par("omd")[3]) # in y coordinates
+y.mid.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
+y.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4])) # in y coordinates
+y.mid.bottom.fig.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] / 2) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
+y.bottom.fig.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3]) # in y coordinates
+y.mid.top.fig.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
+y.top.fig.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4])) # in y coordinates
+y.top.plot.region <- par("usr")[4] # in y coordinates, top of the plot region (according to y scale)
+y.bottom.plot.region <- par("usr")[3] # in y coordinates, bottom of the plot region (according to y scale)
+y.mid.plot.region <- ((par("usr")[3] + par("usr")[4]) / 2) # in x coordinates, right of the plot region (according to x scale)
+}
+if(any(sapply(FUN = all.equal, c(1, 3), x.side) == TRUE)){
+par(xpd=FALSE, xaxt="s")
+if(is.null(x.categ) & x.log.scale == TRUE){
+if(any(par()$xaxp[1:2] == 0L)){ # any(sapply(FUN = all.equal, par()$xaxp[1:2], 0) == TRUE) not used because we strictly need zero as a result. Beware: write "== TRUE", because the result is otherwise character and a warning message appears using any()
+if(par()$xaxp[1] == 0L){ # isTRUE(all.equal(par()$xaxp[1], 0)) not used because we strictly need zero as a result
+par(xaxp = c(10^-30, par()$xaxp[2:3])) # because log10(par()$xaxp[1] == 0) == -Inf
+}
+if(par()$xaxp[2] == 0L){ # isTRUE(all.equal(par()$xaxp[1], 0)) not used because we strictly need zero as a result
+par(xaxp = c(par()$xaxp[1], 10^-30, par()$xaxp[3])) # because log10(par()$xaxp[2] == 0) == -Inf
+}
+}
+axis(side = x.side, at = c(10^par()$usr[1], 10^par()$usr[2]), labels=rep("", 2), lwd=1, lwd.ticks = 0) # draw the axis line
+mtext(side = x.side, text = x.lab, line = x.dist.legend / 0.2, las = 0, cex = x.label.size)
+par(tcl = -par()$mgp[2] * sec.tick.length) # length of the secondary ticks are reduced
+suppressWarnings(rug(10^outer(c((log10(par("xaxp")[1]) -1):log10(par("xaxp")[2])), log10(1:10), "+"), ticksize = NA, side = x.side)) # ticksize = NA to allow the use of par()$tcl value
+par(tcl = -par()$mgp[2] * tick.length) # back to main ticks
+axis(side = x.side, at = c(1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10), labels = expression(10^-15, 10^-14, 10^-13, 10^-12, 10^-11, 10^-10, 10^-9, 10^-8, 10^-7, 10^-6, 10^-5, 10^-4, 10^-3, 10^-2, 10^-1, 10^0, 10^1, 10^2, 10^3, 10^4, 10^5, 10^6, 10^7, 10^8, 10^9, 10^10), lwd = 0, lwd.ticks = 1, cex.axis = x.axis.size)
+x.text <- 10^par("usr")[2]
+}else if(is.null(x.categ) & x.log.scale == FALSE){
+axis(side=x.side, at=c(par()$usr[1], par()$usr[2]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
+axis(side=x.side, at=round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), cex.axis = x.axis.size) # axis(side=x.side, at=round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), labels = format(round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), big.mark=','), cex.axis = x.axis.size) # to get the 1000 comma separator
+mtext(side = x.side, text = x.lab, line = x.dist.legend / 0.2, las = 0, cex = x.label.size)
+if(x.nb.inter.tick > 0){
+inter.tick.unit <- (par("xaxp")[2] - par("xaxp")[1]) / par("xaxp")[3]
+par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
+suppressWarnings(rug(seq(par("xaxp")[1] - 10 * inter.tick.unit, par("xaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + x.nb.inter.tick)), ticksize = NA, x.side)) # ticksize = NA to allow the use of par()$tcl value
+par(tcl = -par()$mgp[2] * tick.length) # back to main ticks
+}
+x.text <- par("usr")[2]
+}else if(( ! is.null(x.categ)) & x.log.scale == FALSE){
+if(is.null(x.categ.pos)){
+x.categ.pos <- 1:length(x.categ)
+}else if(length(x.categ.pos) != length(x.categ)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.categ.pos MUST BE THE SAME LENGTH AS x.categ")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+par(xpd = TRUE)
+if(isTRUE(all.equal(x.side, 1))){ #isTRUE(all.equal(x.side, 1)) is similar to x.side == 1L but deals with float
+segments(x0 = x.left.plot.region, x1 = x.right.plot.region, y0 = y.bottom.plot.region, y1 = y.bottom.plot.region) # draw the line of the axis
+text(x = x.categ.pos, y = y.mid.bottom.fig.region, labels = x.categ, srt = text.angle, cex = x.axis.size)
+}else if(isTRUE(all.equal(x.side, 3))){ #isTRUE(all.equal(x.side, 1)) is similar to x.side == 3L but deals with float
+segments(x0 = x.left.plot.region, x1 = x.right.plot.region, y0 = y.top.plot.region, y1 = y.top.plot.region) # draw the line of the axis
+text(x = x.categ.pos, y = y.mid.top.fig.region, labels = x.categ, srt = text.angle, cex = x.axis.size)
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": ARGUMENT x.side CAN ONLY BE 1 OR 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+par(xpd = FALSE)
+x.text <- par("usr")[2]
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": PROBLEM WITH THE x.side (", x.side ,") OR x.log.scale (", x.log.scale,") ARGUMENTS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+x.text <- par("usr")[2]
+}
+if(any(sapply(FUN = all.equal, c(2, 4), y.side) == TRUE)){
+par(xpd=FALSE, yaxt="s")
+if(is.null(y.categ) & y.log.scale == TRUE){
+if(any(par()$yaxp[1:2] == 0L)){ # any(sapply(FUN = all.equal, par()$yaxp[1:2], 0) == TRUE) not used because we strictly need zero as a result. Beware: write "== TRUE", because the result is otherwise character and a warning message appears using any()
+if(par()$yaxp[1] == 0L){ # strict zero needed
+par(yaxp = c(10^-30, par()$yaxp[2:3])) # because log10(par()$yaxp[1] == 0) == -Inf
+}
+if(par()$yaxp[2] == 0L){ # strict zero needed
+par(yaxp = c(par()$yaxp[1], 10^-30, par()$yaxp[3])) # because log10(par()$yaxp[2] == 0) == -Inf
+}
+}
+axis(side=y.side, at=c(10^par()$usr[3], 10^par()$usr[4]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
+par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
+suppressWarnings(rug(10^outer(c((log10(par("yaxp")[1])-1):log10(par("yaxp")[2])), log10(1:10), "+"), ticksize = NA, side = y.side)) # ticksize = NA to allow the use of par()$tcl value
+par(tcl = -par()$mgp[2] * tick.length) # back to main tick length
+axis(side = y.side, at = c(1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10), labels = expression(10^-15, 10^-14, 10^-13, 10^-12, 10^-11, 10^-10, 10^-9, 10^-8, 10^-7, 10^-6, 10^-5, 10^-4, 10^-3, 10^-2, 10^-1, 10^0, 10^1, 10^2, 10^3, 10^4, 10^5, 10^6, 10^7, 10^8, 10^9, 10^10), lwd = 0, lwd.ticks = 1, cex.axis = y.axis.size)
+y.text <- 10^(par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
+mtext(side = y.side, text = y.lab, line = y.dist.legend / 0.2, las = 0, cex = y.label.size)
+}else if(is.null(y.categ) & y.log.scale == FALSE){
+axis(side=y.side, at=c(par()$usr[3], par()$usr[4]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
+axis(side=y.side, at=round(seq(par()$yaxp[1], par()$yaxp[2], length.out=par()$yaxp[3]+1), 2), cex.axis = y.axis.size)
+mtext(side = y.side, text = y.lab, line = y.dist.legend / 0.2, las = 0, cex = y.label.size)
+if(y.nb.inter.tick > 0){
+inter.tick.unit <- (par("yaxp")[2] - par("yaxp")[1]) / par("yaxp")[3]
+par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
+suppressWarnings(rug(seq(par("yaxp")[1] - 10 * inter.tick.unit, par("yaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + y.nb.inter.tick)), ticksize = NA, side=y.side)) # ticksize = NA to allow the use of par()$tcl value
+par(tcl = -par()$mgp[2] * tick.length) # back to main tick length
+}
+y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
+}else if(( ! is.null(y.categ)) & y.log.scale == FALSE){
+if(is.null(y.categ.pos)){
+y.categ.pos <- 1:length(y.categ)
+}else if(length(y.categ.pos) != length(y.categ)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.categ.pos MUST BE THE SAME LENGTH AS y.categ")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+axis(side = y.side, at = y.categ.pos, labels = rep("", length(y.categ)), lwd=0, lwd.ticks=1) # draw the line of the axis
+par(xpd = TRUE)
+if(isTRUE(all.equal(y.side, 2))){ #isTRUE(all.equal(y.side, 2)) is similar to y.side == 2L but deals with float
+text(x = x.mid.left.fig.region, y = y.categ.pos, labels = y.categ, srt = text.angle, cex = y.axis.size)
+}else if(isTRUE(all.equal(y.side, 4))){ # idem
+text(x = x.mid.right.fig.region, y = y.categ.pos, labels = y.categ, srt = text.angle, cex = y.axis.size)
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": ARGUMENT y.side CAN ONLY BE 2 OR 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+par(xpd = FALSE)
+y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": PROBLEM WITH THE y.side (", y.side ,") OR y.log.scale (", y.log.scale,") ARGUMENTS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
+}
+par(xpd=NA)
+text(x = x.mid.right.fig.region, y = y.text, corner.text, adj=c(1, 1.1), cex = corner.text.size) # text at the topright corner. Replace x.right.fig.region by x.text if text at the right edge of the plot region
+if(just.label.add == TRUE & isTRUE(all.equal(x.side, 0)) & x.lab != ""){
+text(x = x.mid.plot.region, y = y.mid.bottom.fig.region, x.lab, adj=c(0.5, 0.5), cex = x.label.size) # x label
+}
+if(just.label.add == TRUE & isTRUE(all.equal(y.side, 0)) & y.lab != ""){
+text(x = y.mid.plot.region, y = x.mid.left.fig.region, y.lab, adj=c(0.5, 0.5), cex = y.label.size) # x label
+}
+par(xpd=FALSE)
+if(par.reset == TRUE){
+tempo.par <- fun_open(pdf = FALSE, return.output = TRUE)
+invisible(dev.off()) # close the new window
+if( ! is.null(custom.par)){
+if( ! names(custom.par) %in% names(tempo.par$ini.par)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": custom.par ARGUMENT SHOULD HAVE THE NAMES OF THE COMPARTMENT LIST COMING FROM THE par() LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+par(custom.par)
+text <- c(text, "\nGRAPH PARAMETERS SET TO VALUES DEFINED BY custom.par ARGUMENT\n")
+}else{
+par(tempo.par$ini.par)
+text <- c(text, "\nGRAPH PARAMETERS RESET TO par() DEFAULT VALUES\n")
+}
+}
+output <- list(x.mid.left.dev.region = x.mid.left.dev.region, x.left.dev.region = x.left.dev.region, x.mid.right.dev.region = x.mid.right.dev.region, x.right.dev.region = x.right.dev.region, x.mid.left.fig.region = x.mid.left.fig.region, x.left.fig.region = x.left.fig.region, x.mid.right.fig.region = x.mid.right.fig.region, x.right.fig.region = x.right.fig.region, x.left.plot.region = x.left.plot.region, x.right.plot.region = x.right.plot.region, x.mid.plot.region = x.mid.plot.region, y.mid.bottom.dev.region = y.mid.bottom.dev.region, y.bottom.dev.region = y.bottom.dev.region, y.mid.top.dev.region = y.mid.top.dev.region, y.top.dev.region = y.top.dev.region, y.mid.bottom.fig.region = y.mid.bottom.fig.region, y.bottom.fig.region = y.bottom.fig.region, y.mid.top.fig.region = y.mid.top.fig.region, y.top.fig.region = y.top.fig.region, y.top.plot.region = y.top.plot.region, y.bottom.plot.region = y.bottom.plot.region, y.mid.plot.region = y.mid.plot.region, text = text)
+return(output)
+}
+
+
+######## fun_close() #### close specific graphic windows
+
+
+fun_close <- function(kind = "pdf", return.text = FALSE){
+# AIM
+# close only specific graphic windows (devices)
+# ARGUMENTS:
+# kind: vector, among c("windows", "quartz", "x11", "X11", "pdf", "bmp", "png", "tiff"), indicating the kind of graphic windows (devices) to close. BEWARE: either "windows", "quartz", "x11" or "X11" means that all the X11 GUI graphics devices will be closed, whatever the OS used
+# return.text: print text regarding the kind parameter and the devices that were finally closed?
+# RETURN
+# text regarding the kind parameter and the devices that were finally closed
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# windows() ; windows() ; pdf() ; dev.list() ; fun_close(kind = c("pdf", "x11"), return.text = TRUE) ; dev.list()
+# DEBUGGING
+# kind = c("windows", "pdf") ; return.text = FALSE # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = kind, options = c("windows", "quartz", "x11", "X11", "pdf", "bmp", "png", "tiff"), fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.text, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+text <- paste0("THE REQUIRED KIND OF GRAPHIC DEVICES TO CLOSE ARE ", paste(kind, collapse = " "))
+if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
+if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
+tempo <- kind %in% c("windows", "quartz", "x11", "X11")
+kind[tempo] <- "windows" # term are replaced by what is displayed when using a <- dev.list() ; names(a)
+}
+}else if(Sys.info()["sysname"] == "Linux"){
+if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
+tempo.device <- suppressWarnings(try(X11(), silent = TRUE))[] # open a X11 window to try to recover the X11 system used
+if( ! is.null(tempo.device)){
+text <- paste0(text, "\nCANNOT CLOSE GUI GRAPHIC DEVICES AS REQUIRED BECAUSE THIS LINUX SYSTEM DOES NOT HAVE IT")
+}else{
+tempo <- kind %in% c("windows", "quartz", "x11", "X11")
+kind[tempo] <- names(dev.list()[length(dev.list())]) # term are replaced by what is displayed when using a <- dev.list() ; names(a)
+invisible(dev.off()) # close the X11 opened by tempo
+}
+}
+}else{ # for macOS
+if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
+tempo <- kind %in% c("windows", "quartz", "x11", "X11")
+kind[tempo] <- "quartz" # term are replaced by what is displayed when using a <- dev.list() ; names(a)
+}
+}
+kind <- unique(kind)
+if(length(dev.list()) != 0){
+for(i in length(names(dev.list())):1){
+if(names(dev.list())[i] %in% kind){
+text <- paste0(text, "\n", names(dev.list())[i], " DEVICE NUMBER ", dev.list()[i], " HAS BEEN CLOSED")
+invisible(dev.off(dev.list()[i]))
+}
+}
+}
+if(return.text == TRUE){
+return(text)
+}
+}
+
+
+################ Standard graphics
+
+
+######## fun_empty_graph() #### text to display for empty graphs
+
+
+ 
+
+
+fun_empty_graph <- function(
+text = NULL, 
+text.size = 1, 
+title = NULL, 
+title.size = 1.5
+){
+# AIM
+# display an empty plot with a text in the middle of the window (for instance to specify that no plot can be drawn)
+# ARGUMENTS
+# text: character string of the message to display
+# text.size: numeric value of the text size
+# title: character string of the graph title
+# title.size: numeric value of the title size (in points)
+# RETURN
+# an empty plot
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# simple example
+# fun_empty_graph(text = "NO GRAPH")
+# white page
+# fun_empty_graph() # white page
+# all the arguments
+# fun_empty_graph(text = "NO GRAPH", text.size = 2, title = "GRAPH1", title.size = 1)
+# DEBUGGING
+# text = "NO GRAPH" ; title = "GRAPH1" ; text.size = 1
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if( ! is.null(text)){
+tempo <- fun_check(data = text, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(title)){
+tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = title.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+ini.par <- par(no.readonly = TRUE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
+par(ann=FALSE, xaxt="n", yaxt="n", mar = rep(1, 4), bty = "n", xpd = NA)
+plot(1, 1, type = "n") # no display with type = "n"
+x.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1])
+y.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]))
+if( ! is.null(text)){
+text(x = 1, y = 1, labels = text, cex = text.size)
+}
+if( ! is.null(title)){
+text(x = x.left.dev.region, y = y.top.dev.region, labels = title, adj=c(0, 1), cex = title.size)
+}
+par(ini.par)
+}
+
+
+################ gg graphics
+
+
+######## fun_gg_palette() #### ggplot2 default color palette
+
+
+ 
+
+
+fun_gg_palette <- function(n, kind = "std"){
+# AIM
+# provide colors used by ggplot2
+# the interest is to use another single color that is not the red one used by default
+# for ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
+# ARGUMENTS
+# n: number of groups on the graph
+# kind: either "std" for standard gg colors, "dark" for darkened gg colors, or "light" for pastel gg colors
+# RETURN
+# the vector of hexadecimal colors
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# output of the function
+# fun_gg_palette(n = 2)
+# the ggplot2 palette when asking for 7 different colors
+# plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7))
+# selection of the 5th color of the ggplot2 palette made of 7 different colors
+# plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7)[5])
+# the ggplot2 palette made of 7 darkened colors
+# plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7, kind = "dark"))
+# the ggplot2 palette made of 7 lighten colors
+# plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7, kind = "light"))
+# DEBUGGING
+# n = 0
+# kind = "std"
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = n, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & isTRUE(all.equal(n, 0))){ # isTRUE(all.equal(n, 0))) is similar to n == 0 but deals with float
+tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A NON ZERO INTEGER. HERE IT IS: ", paste(n, collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+tempo <- fun_check(data = kind, options = c("std", "dark", "light"), length = 1, fun.name = function.name) ; eval(ee)
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+hues = seq(15, 375, length = n + 1)
+hcl(h = hues, l = if(kind == "std"){65}else if(kind == "dark"){35}else if(kind == "light"){85}, c = 100)[1:n]
+}
+
+
+######## fun_gg_just() #### ggplot2 justification of the axis labeling, depending on angle
+
+
+ 
+
+
+fun_gg_just <- function(angle, pos, kind = "axis"){
+# AIM
+# provide correct justification for text labeling, depending on the chosen angle
+# WARNINGS
+# justification behave differently on plot, depending whether it is used for annotayed text or for axis labelling. Indeed the latter has labelling constrained
+# Of note, a bug in ggplot2: vjust sometimes does not work, i.e., the same justification result is obtained whatever the value used. This is the case with angle = 90, pos = "top", kind = "axis". While everything is fine with angle = 90, pos = "bottom", kind = "axis". At least, everything seems fine for kind = "axis" and pos = c("left", "bottom")
+# ARGUMENTS
+# angle: integer value of the text angle, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc. 
+# pos: where text is? Either "top", "right", "bottom" or "left" of the elements to justify from
+# kind: kind of text? Either "axis" or "text". In the first case, the pos argument refers to the axis position, and in the second to annotated text (using ggplot2::annotate() or ggplot2::geom_text())
+# RETURN
+# a list containing:
+# $angle: the submitted angle (value potentially reduced to fit the [-360 ; 360] interval, e.g., 460 -> 100, without impact on the final angle displayed)
+# $pos: the selected position (argument pos)
+# $kind: the selected kind of text (argument kind)
+# $hjust: the horizontal justification
+# $vjust: the vertical justification
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_gg_just(angle = 45, pos = "bottom")
+# fun_gg_just(angle = (360*2 + 45), pos = "left")
+# output <- fun_gg_just(angle = 45, pos = "bottom") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust))
+# output <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.y = ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)) + ggplot2::coord_flip()
+# output1 <- fun_gg_just(angle = 90, pos = "bottom") ; output2 <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = output1$angle, hjust = output1$hjust, vjust = output1$vjust), axis.text.y = ggplot2::element_text(angle = output2$angle, hjust = output2$hjust, vjust = output2$vjust))
+# output <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1, km = 1, bird = "pigeon", stringsAsFactors = FALSE) ; ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point() + ggplot2::geom_text(mapping = ggplot2::aes(label = bird), angle = output$angle, hjust = output$hjust, vjust = output$vjust)
+# obs1 <- data.frame(time = 1:10, km = 1:10, bird = c(NA, NA, NA, "pigeon", NA, "cat", NA, NA, NA, NA), stringsAsFactors = FALSE) ; fun_open(width = 4, height = 4) ; for(i0 in c("text", "axis")){for(i1 in c("top", "right", "bottom", "left")){for(i2 in c(0, 45, 90, 135, 180, 225, 270, 315, 360)){output <- fun_gg_just(angle = i2, pos = i1, kind = i0) ; title <- paste0("kind: ", i0, " | pos: ", i1, " | angle = ", i2, " | hjust: ", output$hjust, " | vjust: ", output$vjust) ; if(i0 == "text"){print(ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point(color = fun_gg_palette(1), alpha = 0.5) + ggplot2::ggtitle(title) + ggplot2::geom_text(mapping = ggplot2::aes(label = bird), angle = output$angle, hjust = output$hjust, vjust = output$vjust) + ggplot2::theme(title = ggplot2::element_text(size = 5)))}else{print(ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point(color = fun_gg_palette(1), alpha = 0.5) + ggplot2::ggtitle(title) + ggplot2::geom_text(mapping = ggplot2::aes(label = bird)) + ggplot2::scale_x_continuous(position = ifelse(i1 == "top", "top", "bottom")) + ggplot2::scale_y_continuous(position = ifelse(i1 == "right", "right", "left")) + ggplot2::theme(title = ggplot2::element_text(size = 5), axis.text.x = if(i1 %in% c("top", "bottom")){ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)}, axis.text.y = if(i1 %in% c("right", "left")){ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)}))}}}} ; dev.off()
+# DEBUGGING
+# angle = 45 ; pos = "left" ; kind = "axis"
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument primary checking
+# arg with no default values
+mandat.args <- c(
+"angle", 
+"pos"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# using fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = angle, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = pos, options = c("left", "top", "right", "bottom"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = kind, options = c("axis", "text"), length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <- c(
+"angle", 
+"pos", 
+"kind"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# end second round of checking and data preparation
+# main code
+# to get angle between -360 and 360
+while(angle > 360){
+angle <- angle - 360
+}
+while(angle < -360){
+angle <- angle + 360
+}
+# end to get angle between -360 and 360
+# justifications
+if(pos %in% c("bottom", "top")){
+# code below is for if(pos == "bottom"){
+if(any(sapply(FUN = all.equal, c(-360, -180, 0, 180, 360), angle) == TRUE)){ # equivalent of angle == -360 | angle == -180 | angle == 0 | angle == 180 | angle == 360 but deals with floats
+hjust <- 0.5
+if(kind == "text"){
+if(any(sapply(FUN = all.equal, c(-360, 0, 360), angle) == TRUE)){
+vjust <- 1
+}else if(any(sapply(FUN = all.equal, c(-180, 180), angle) == TRUE)){
+vjust <- 0
+}
+}else{
+vjust <- 0.5
+}
+}else if(any(sapply(FUN = all.equal, c(-270, 90), angle) == TRUE)){
+hjust <- 1
+vjust <- 0.5
+}else if(any(sapply(FUN = all.equal, c(-90, 270), angle) == TRUE)){
+hjust <- 0
+vjust <- 0.5
+}else if((angle > -360 & angle < -270) | (angle > 0 & angle < 90)){
+hjust <- 1
+vjust <- 1
+}else if((angle > -270 & angle < -180) | (angle > 90 & angle < 180)){
+hjust <- 1
+vjust <- 0
+}else if((angle > -180 & angle < -90) | (angle > 180 & angle < 270)){
+hjust <- 0
+vjust <- 0
+if(kind == "text" & pos == "top"){
+hjust <- 1
+}
+}else if((angle > -90 & angle < 0) | (angle > 270 & angle < 360)){
+hjust <- 0
+vjust <- 1
+}
+if(pos == "top"){
+if( ! ((angle > -180 & angle < -90) | (angle > 180 & angle < 270))){
+hjust <- 1 - hjust
+}
+vjust <- 1 - vjust
+}
+}else if(pos %in% c("left", "right")){
+# code below is for if(pos == "left"){
+if(any(sapply(FUN = all.equal, c(-270, -90, 90, 270), angle) == TRUE)){ # equivalent of angle == -270 | angle == -90 | angle == 90 | angle == 270 but deals with floats
+hjust <- 0.5
+if(kind == "text"){
+if(any(sapply(FUN = all.equal, c(-90, 90), angle) == TRUE)){
+vjust <- 0
+}else if(any(sapply(FUN = all.equal, c(-270, 270), angle) == TRUE)){
+vjust <- 1
+}
+}else{
+vjust <- 0.5
+}
+}else if(any(sapply(FUN = all.equal, c(-360, 0, 360), angle) == TRUE)){
+hjust <- 1
+vjust <- 0.5
+}else if(any(sapply(FUN = all.equal, c(-180, 180), angle) == TRUE)){
+hjust <- 0
+vjust <- 0.5
+}else if((angle > -360 & angle < -270) | (angle > 0 & angle < 90)){
+hjust <- 1
+vjust <- 0
+}else if((angle > -270 & angle < -180) | (angle > 90 & angle < 180)){
+hjust <- 0
+vjust <- 0
+}else if((angle > -180 & angle < -90) | (angle > 180 & angle < 270)){
+hjust <- 0
+vjust <- 1
+}else if((angle > -90 & angle < 0) | (angle > 270 & angle < 360)){
+hjust <- 1
+vjust <- 1
+}
+if(pos == "right"){
+hjust <- 1 - hjust
+if( ! (((angle > -270 & angle < -180) | (angle > 90 & angle < 180)) | ((angle > -180 & angle < -90) | (angle > 180 & angle < 270)))){
+vjust <- 1 - vjust
+}
+}
+}
+# end justifications
+output <- list(angle = angle, pos = pos, kind = kind, hjust = hjust, vjust = vjust)
+return(output)
+}
+
+
+######## fun_gg_get_legend() #### get the legend of ggplot objects
+
+
+ 
+
+
+fun_gg_get_legend <- function(ggplot_built, fun.name = NULL, lib.path = NULL){
+# AIM
+# get legend of ggplot objects
+# # from https://stackoverflow.com/questions/12539348/ggplot-separate-legend-and-plot
+# ARGUMENTS
+# ggplot_built: a ggplot build object
+# fun.name: single character string indicating the name of the function using fun_gg_get_legend() for warning and error messages. Ignored if NULL
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# RETURN
+# a list of class c("gtable", "gTree", "grob", "gDesc"), providing legend information of ggplot_built objet, or NULL if the ggplot_built object has no legend
+# REQUIRED PACKAGES
+# ggplot2
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# EXAMPLES
+# Simple example
+# obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time, fill = group)) ; fun_gg_get_legend(ggplot_built = ggplot2::ggplot_build(p))
+# Error message because no legend in the ggplot
+# obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time)) ; fun_gg_get_legend(ggplot_built = ggplot2::ggplot_build(p))
+# DEBUGGING
+# obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time)) ; ggplot_built = ggplot2::ggplot_build(p) ; fun.name = NULL ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+req.function <- c(
+"fun_check",
+"fun_pack"
+)
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED ", i1, "() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end required function checking
+# argument primary checking
+# arg with no default values
+mandat.args <- c(
+"ggplot_built"
+)
+tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# using fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = ggplot_built, class = "ggplot_built", mode = "list", fun.name = function.name) ; eval(ee)
+if( ! is.null(fun.name)){
+tempo <- fun_check(data = fun.name, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(arg.check)){
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+}
+# end using fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking
+# management of NA
+if(any(is.na(ggplot_built)) | any(is.na(fun.name)) | any(is.na(lib.path))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": NO ARGUMENT CAN HAVE NA VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA
+# management of NULL
+if(is.null(ggplot_built)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nggplot_built ARGUMENT CANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL
+if( ! is.null(lib.path)){
+if( ! all(dir.exists(lib.path))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end second round of checking
+# package checking
+fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
+# end package checking
+# main code
+win.nb <- dev.cur()
+pdf(file = NULL)
+tmp <- ggplot2::ggplot_gtable(ggplot_built)
+# BEWARE with ggplot_gtable : open a blanck device https://stackoverflow.com/questions/17012518/why-does-this-r-ggplot2-code-bring-up-a-blank-display-device
+invisible(dev.off())
+if(win.nb > 1){ # to go back to the previous active device, if == 1 means no opened device
+dev.set(win.nb)
+}
+leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
+if(length(leg) == 0L){
+legend <- NULL
+}else{
+legend <- tmp$grobs[[leg]]
+}
+return(legend)
+}
+
+
+######## fun_gg_point_rast() #### ggplot2 raster scatterplot layer
+
+
+ 
+
+
+fun_gg_point_rast <- function(
+data = NULL, 
+mapping = NULL, 
+stat = "identity", 
+position = "identity", 
+..., 
+na.rm = FALSE, 
+show.legend = NA, 
+inherit.aes = TRUE, 
+raster.width = NULL, 
+raster.height = NULL, 
+raster.dpi = 300, 
+inactivate = TRUE, 
+lib.path = NULL
+){
+# AIM
+# equivalent to ggplot2::geom_point() but in raster mode
+# use it like ggplot2::geom_point() with the main raster.dpi additional argument
+# WARNINGS
+# can be long to generate the plot
+# use a square plot region. Otherwise, the dots will have ellipsoid shape
+# solve the transparency problems with some GUI
+# this function is derived from the geom_point_rast() function, created by Viktor Petukhov , and present in the ggrastr package (https://rdrr.io/github/VPetukhov/ggrastr/src/R/geom-point-rast.R, MIT License, Copyright (c) 2017 Viktor Petukhov). Has been placed here to minimize package dependencies
+# ARGUMENTS
+# classical arguments of geom_point(), shown here https://rdrr.io/github/VPetukhov/ggrastr/man/geom_point_rast.html
+# raster.width : width of the result image (in inches). Default: deterined by the current device parameters
+# raster.height: height of the result image (in inches). Default: deterined by the current device parameters
+# raster.dpi: resolution of the result image
+# inactivate: logical. Inactivate the fun.name argument of the fun_check() function? If TRUE, the name of the fun_check() function in error messages coming from this function. Use TRUE if fun_gg_point_rast() is used like this: eval(parse(text = "fun_gg_point_rast"))
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# RETURN
+# a raster scatter plot
+# REQUIRED PACKAGES
+# ggplot2
+# grid (included in the R installation packages but not automatically loaded)
+# Cairo
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# EXAMPLES
+# Two pdf in the current directory
+# set.seed(1) ; data1 = data.frame(x = rnorm(100000), y = rnorm(10000), stringsAsFactors = TRUE) ; fun_open(pdf.name = "Raster") ; ggplot2::ggplot() + fun_gg_point_rast(data = data1, mapping = ggplot2::aes(x = x, y = y)) ; fun_open(pdf.name = "Vectorial") ; ggplot2::ggplot() + ggplot2::geom_point(data = data1, mapping = ggplot2::aes(x = x, y = y)) ; dev.off() ; dev.off()
+# DEBUGGING
+# 
+# function name
+if(all(inactivate == FALSE)){ # inactivate has to be used here but will be fully checked below
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+}else if(all(inactivate == TRUE)){
+function.name <- NULL
+}else{
+tempo.cat <- paste0("ERROR IN fun_gg_point_rast(): CODE INCONSISTENCY 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if( ! is.null(data)){
+tempo <- fun_check(data = data, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(mapping)){
+tempo <- fun_check(data = mapping, class = "uneval", typeof = "list", fun.name = function.name) ; eval(ee) # aes() is tested
+}
+# stat and position not tested because too complicate
+tempo <- fun_check(data = na.rm, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = show.legend, class = "vector", mode = "logical", length = 1, na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = inherit.aes, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(raster.width)){
+tempo <- fun_check(data = raster.width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(raster.height)){
+tempo <- fun_check(data = raster.height, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = raster.dpi, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = inactivate, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# package checking
+fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
+fun_pack(req.package = c("grid"), lib.path = lib.path)
+fun_pack(req.package = c("Cairo"), lib.path = lib.path)
+# end package checking
+# additional functions
+DrawGeomPointRast <- function(data, panel_params, coord, na.rm = FALSE, raster.width = NULL, raster.height= NULL, raster.dpi = raster.dpi){
+if (is.null(raster.width)){
+raster.width <- par('fin')[1]
+}
+if (is.null(raster.height)){
+ raster.height <- par('fin')[2]
+}
+prev_dev_id <- dev.cur()
+p <- ggplot2::GeomPoint$draw_panel(data, panel_params, coord)
+dev_id <- Cairo::Cairo(type='raster', width = raster.width*raster.dpi, height = raster.height*raster.dpi, dpi = raster.dpi, units = 'px', bg = "transparent")[1]
+grid::pushViewport(grid::viewport(width = 1, height = 1))
+grid::grid.points(x = p$x, y = p$y, pch = p$pch, size = p$size,
+name = p$name, gp = p$gp, vp = p$vp, draw = T)
+grid::popViewport()
+cap <- grid::grid.cap()
+invisible(dev.off(dev_id))
+invisible(dev.set(prev_dev_id))
+grid::rasterGrob(cap, x = 0, y = 0, width = 1, height = 1, default.units = "native", just = c("left","bottom"))
+}
+# end additional functions
+# main code
+GeomPointRast <- ggplot2::ggproto("GeomPointRast", ggplot2::GeomPoint, draw_panel = DrawGeomPointRast)
+ggplot2::layer(
+data = data, 
+mapping = mapping, 
+stat = stat, 
+geom = GeomPointRast, 
+position = position, 
+show.legend = show.legend, 
+inherit.aes = inherit.aes, 
+params = list(
+na.rm = na.rm, 
+raster.width = raster.width, 
+raster.height = raster.height, 
+raster.dpi = raster.dpi, 
+...
+)
+)
+# end main code
+}
+
+
+######## fun_gg_boxplot() #### ggplot2 boxplot + background dots if required
+
+
+
+
+######## fun_gg_scatter() #### ggplot2 scatterplot + lines (up to 6 overlays totally)
+
+
+
+
+######## fun_gg_heatmap() #### ggplot2 heatmap + overlaid mask if required
+
+
+#test plot.margin = margin(up.space.mds, right.space.mds, down.space.mds, left.space.mds, "inches") to set the dim of the region plot ?
+# if matrix is full of zero (or same value I guess), heatmap is complicate. Test it and error message
+
+fun_gg_heatmap <- function(
+data1, 
+legend.name1 = "", 
+low.color1 = "blue", 
+mid.color1 = "white", 
+high.color1 = "red", 
+limit1 = NULL, 
+midpoint1 = NULL, 
+data2 = NULL, 
+color2 = "black", 
+alpha2 = 0.5, 
+invert2 = FALSE, 
+text.size = 12, 
+title = "", 
+title.text.size = 12, 
+show.scale = TRUE, 
+rotate = FALSE, 
+return = FALSE, 
+plot = TRUE, 
+add = NULL, 
+warn.print = FALSE, 
+lib.path = NULL
+){
+# AIM
+# ggplot2 heatmap with the possibility to overlay a mask
+# see also:
+# draw : http://www.sthda.com/english/wiki/ggplot2-quick-correlation-matrix-heatmap-r-software-and-data-visualization
+# same range scale : https://stackoverflow.com/questions/44655723/r-ggplot2-heatmap-fixed-scale-color-between-graphs 
+# for ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
+# ARGUMENTS
+# data1: numeric matrix or data frame resulting from the conversion of the numeric matrix by reshape2::melt()
+# legend.name1: character string of the data1 heatmap scale legend
+# low.color1: character string of the color (i.e., "blue" or "#0000FF") of the lowest scale value
+# mid.color1: same as low.color1 but for the middle scale value. If NULL, the middle color is the default color between low.color1 and high.color1. BEWARE: argument midpoint1 is not ignored, even if mid.color1 is NULL, meaning that the default mid color can still be controled
+# high.color1: same as low.color1 but for the highest scale value
+# limit1: 2 numeric values defining the lowest and higest color scale values. If NULL, take the range of data1 values
+# midpoint1: single numeric value defining the value corresponding to the mid.color1 argument. A warning message is returned if midpoint1 does not correspond to the mean of limit1 values, because the color scale is not linear anymore. If NULL, takes the mean of limit1 values. Mean of data1, instead of mean of limit1, can be used here if required
+# data2: binary mask matrix (made of 0 and 1) of same dimension as data1 or a data frame resulting from the conversion of the binary mask matrix by reshape2::melt(). Value 1 of data2 will correspond to color2 argument (value 0 will be NA color), and the opposite if invert2 argument is TRUE (inverted mask)
+# color2: color of the 1 values of the binary mask matrix. The 0 values will be color NA
+# alpha2: numeric value (from 0 to 1) of the mask transparency
+# invert2: logical. Invert the mask (1 -> 0 and 0 -> 1)?
+# text.size: numeric value of the size of the texts in scale
+# title: character string of the graph title
+# title.text.size: numeric value of the title size (in points)
+# show.scale: logical. Show color scale?
+# rotate: logical. Rotate the heatmap 90° clockwise?
+# return: logical. Return the graph parameters?
+# plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
+# add: character string allowing to add more ggplot2 features (dots, lines, themes, etc.). BEWARE: (1) must start with "+" just after the simple or double opening quote (no space, end of line, carriage return, etc., allowed), (2) must finish with ")" just before the simple or double closing quote (no space, end of line, carriage return, etc., allowed) and (3) each function must be preceded by "ggplot2::" (for instance: "ggplot2::coord_flip()). If the character string contains the "ggplot2::theme" string, then internal ggplot2 theme() and theme_classic() functions will be inactivated to be reused by add. BEWARE: handle this argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
+# warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
+# lib.path: absolute path of the required packages, if not in the default folders
+# RETURN
+# a heatmap if plot argument is TRUE
+# a list of the graph info if return argument is TRUE:
+# $data: a list of the graphic info
+# $axes: a list of the axes info
+# $scale: the scale info (lowest, mid and highest values)
+# $warn: the warning messages. Use cat() for proper display. NULL if no warning
+# REQUIRED PACKAGES
+# ggplot2
+# reshape2
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# fun_round()
+# EXAMPLES
+# fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), title = "GRAPH 1")
+# fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), return = TRUE)
+# fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), legend.name1 = "VALUE", title = "GRAPH 1", text.size = 5, data2 = matrix(rep(c(1,0,0,0), 4), ncol = 4), invert2 = FALSE, return = TRUE)
+# diagonal matrix
+# fun_gg_heatmap(data1 = matrix(c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1), ncol = 4))
+# fun_gg_heatmap(data1 = reshape2::melt(matrix(c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1), ncol = 4)))
+# error message
+# fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), data2 = matrix(rep(c(1,0,0,0), 5), ncol = 5))
+# fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), data2 = reshape2::melt(matrix(rep(c(1,0,0,0), 4), ncol = 4)))
+# fun_gg_heatmap(data1 = reshape2::melt(matrix(1:16, ncol = 4)), data2 = reshape2::melt(matrix(rep(c(1,0,0,0), 4), ncol = 4)))
+# DEBUGGING
+# data1 = matrix(1:16, ncol = 4) ; legend.name1 = "" ; low.color1 = "blue" ; mid.color1 = "white" ; high.color1 = "red" ; limit1 = NULL ; midpoint1 = NULL ; data2 = matrix(rep(c(1,0,0,0), 4), ncol = 4) ; color2 = "black" ; alpha2 = 0.5 ; invert2 = FALSE ; text.size = 12 ; title = "" ; title.text.size = 12 ; show.scale = TRUE ; rotate = FALSE ; return = FALSE ; plot = TRUE ; add = NULL ; warn.print = TRUE ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_round", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_round() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# no reserved words required for this function
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if(all(is.matrix(data1))){
+tempo <- fun_check(data = data1, class = "matrix", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}else if(all(is.data.frame(data1))){
+tempo <- fun_check(data = data1, class = "data.frame", length = 3, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+# structure of reshape2::melt() data frame
+tempo <- fun_check(data = data1[, 1], data.name = "COLUMN 1 OF data1 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = data1[, 2], data.name = "COLUMN 2 OF data1 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = data1[, 3], data.name = "COLUMN 3 OF data1 (reshape2::melt() DATA FRAME)", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A NUMERIC MATRIX OR A DATA FRAME OUTPUT OF THE reshape::melt() FUNCTION")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = legend.name1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = low.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (all(low.color1 %in% colors() | grepl(pattern = "^#", low.color1)))){ # check that all strings of low.color1 start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": low.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(mid.color1)){
+tempo <- fun_check(data = mid.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (all(mid.color1 %in% colors() | grepl(pattern = "^#", mid.color1)))){ # check that all strings of mid.color1 start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": mid.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = high.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (all(high.color1 %in% colors() | grepl(pattern = "^#", high.color1)))){ # check that all strings of high.color1 start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": high.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(limit1)){
+tempo <- fun_check(data = limit1, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & any(limit1 %in% c(Inf, -Inf))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": limit1 ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+if( ! is.null(midpoint1)){
+tempo <- fun_check(data = midpoint1, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(data2)){
+if(all(is.matrix(data2))){
+tempo <- fun_check(data = data2, class = "matrix", mode = "numeric", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! all(unique(data2) %in% c(0,1))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX IN data2 MUST BE MADE OF 0 AND 1 ONLY (MASK MATRIX)")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & all(is.matrix(data1)) & ! identical(dim(data1), dim(data2))){ # matrix and matrix
+tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX DIMENSION IN data2 MUST BE IDENTICAL AS MATRIX DIMENSION IN data1. HERE IT IS RESPECTIVELY:\n", paste(dim(data2), collapse = " "), "\n", paste(dim(data1), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & all(is.data.frame(data1)) & nrow(data1) != prod(dim(data2))){ # reshape2 and matrix
+tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME IN data2 MUST HAVE ROW NUMBER EQUAL TO PRODUCT OF DIMENSIONS OF data1 MATRIX. HERE IT IS RESPECTIVELY:\n", paste(nrow(data1), collapse = " "), "\n", paste(prod(dim(data2)), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else if(all(is.data.frame(data2))){
+tempo <- fun_check(data = data2, class = "data.frame", length = 3, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+# structure of reshape2::melt() data frame
+tempo <- fun_check(data = data2[, 1], data.name = "COLUMN 1 OF data2 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = data2[, 2], data.name = "COLUMN 2 OF data2 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = data2[, 3], data.name = "COLUMN 3 OF data2 (reshape2::melt() DATA FRAME)", mode = "numeric", fun.name = function.name) ; eval(ee)
+}
+if(tempo$problem == FALSE & ! all(unique(data2[, 3]) %in% c(0,1))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THIRD COLUMN OF DATA FRAME IN data2 MUST BE MADE OF 0 AND 1 ONLY (MASK DATA FRAME)")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & all(is.data.frame(data1)) & ! identical(dim(data1), dim(data2))){ # data frame and data frame
+tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME DIMENSION IN data2 MUST BE IDENTICAL TO DATA FRAME DIMENSION IN data1. HERE IT IS RESPECTIVELY:\n", paste(dim(data2), collapse = " "), "\n", paste(dim(data1), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & all(is.matrix(data1)) & nrow(data2) != prod(dim(data1))){ # reshape2 and matrix
+tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME IN data2 MUST HAVE ROW NUMBER EQUAL TO PRODUCT OF DIMENSION OF data1 MATRIX. HERE IT IS RESPECTIVELY:\n", paste(nrow(data2), collapse = " "), "\n", paste(prod(dim(data1)), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A NUMERIC MATRIX OR A DATA FRAME OUTPUT OF THE reshape::melt() FUNCTION")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = color2, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (all(color2 %in% colors() | grepl(pattern = "^#", color2)))){ # check that all strings of color2 start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": color2 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = alpha2, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = invert2, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = show.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(add)){
+tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! grepl(pattern = "^\\+", add)){ # check that the add string start by +
+tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & ! grepl(pattern = "ggplot2::", add)){ #
+tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST CONTAIN \"ggplot2::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & ! grepl(pattern = ")$", add)){ # check that the add string  finished by )
+tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# package checking
+fun_pack(req.package = c("reshape2", "ggplot2"), lib.path = lib.path)
+# end package checking
+# main code
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+if(all(is.matrix(data1))){
+data1 <- reshape2::melt(data1) # transform a matrix into a data frame with 2 coordinates columns and the third intensity column
+}
+if(rotate == TRUE){
+data1[, 1] <- rev(data1[, 1])
+}
+if(is.null(limit1)){
+if(any(data1[, 3] %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE THIRD COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+limit1 <- range(data1[, 3], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE limit1 ARGUMENT IS NULL -> RANGE OF data1 ARGUMENT HAS BEEN TAKEN: ", paste(fun_round(limit1), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+if(suppressWarnings(any(limit1 %in% c(Inf, -Inf)))){
+tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED LIMIT CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(is.null(midpoint1)){
+midpoint1 <- mean(limit1, na.rm = TRUE)
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE midpoint1 ARGUMENT IS NULL -> MEAN OF limit1 ARGUMENT HAS BEEN TAKEN: ", paste(fun_round(midpoint1), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else if(fun_round(midpoint1, 9) != fun_round(mean(limit1), 9)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE midpoint1 ARGUMENT (", fun_round(mean(midpoint1), 9), ") DOES NOT CORRESPOND TO THE MEAN OF THE limit1 ARGUMENT (", fun_round(mean(limit1), 9), "). COLOR SCALE IS NOT LINEAR")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data2)){
+if(all(is.matrix(data2))){
+data2 <- reshape2::melt(data2) # transform a matrix into a data frame with 2 coordinates columns and the third intensity column
+}
+if(rotate == TRUE){
+data2[, 1] <- rev(data2[, 1])
+}
+data2[, 3] <- factor(data2[, 3]) # to converte continuous scale into discrete scale
+}
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0 # to facilitate debugging
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggplot())
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data1, mapping = ggplot2::aes_string(x = names(data1)[ifelse(rotate == FALSE, 2, 1)], y = names(data1)[ifelse(rotate == FALSE, 1, 2)], fill = names(data1)[3]), show.legend = show.scale)) # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_fill_gradient2(low = low.color1, high = high.color1, mid = mid.color1, midpoint = midpoint1, limit = limit1, breaks = c(limit1[1], midpoint1, limit1[2]), labels = fun_round(c(limit1[1], midpoint1, limit1[2])), name = legend.name1))
+if( ! is.null(data2)){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data2, mapping = ggplot2::aes_string(x = names(data2)[ifelse(rotate == FALSE, 2, 1)], y = names(data2)[ifelse(rotate == FALSE, 1, 2)], alpha = names(data2)[3]), fill = color2, show.legend = FALSE))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", values = if(invert2 == FALSE){c(0, alpha2)}else{c(alpha2, 0)}, guide = FALSE))
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data2, mapping = ggplot2::aes_string(x = names(data2)[ifelse(rotate == FALSE, 2, 1)], y = names(data2)[ifelse(rotate == FALSE, 1, 2)], group = names(data2)[3]), fill = data2[, 3], alpha = alpha2, show.legend = FALSE)) # BEWARE: this does not work if NA present, because geom_raster() has a tendency to complete empty spaces, and thus, behave differently than geom_tile(). See https://github.com/tidyverse/ggplot2/issues/3025
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_fixed()) # x = y
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_y_reverse())
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
+add.check <- TRUE
+if( ! is.null(add)){ # if add is NULL, then = 0
+if(grepl(pattern = "ggplot2::theme", add) == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT -> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+add.check <- FALSE
+}
+}
+if(add.check == TRUE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_blank(),
+axis.title = ggplot2::element_blank(),
+axis.text = ggplot2::element_blank(),
+axis.ticks = ggplot2::element_blank(),
+panel.background = ggplot2::element_blank()
+))
+}
+if(plot == TRUE){
+# suppressWarnings(
+print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))
+# )
+}else{
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+if(return == TRUE){
+output <- ggplot2::ggplot_build(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "))))
+output <- output$data
+names(output)[1] <- "heatmap"
+if( ! is.null(data2)){
+names(output)[2] <- "mask"
+}
+return(list(data = output, axes = output$layout$panel_params[[1]], scale = c(limit1[1],  midpoint1, limit1[2]), warn = warn))
+}
+}
+
+
+######## fun_gg_empty_graph() #### text to display for empty graphs
+
+
+ 
+
+
+fun_gg_empty_graph <- function(
+text = NULL, 
+text.size = 12, 
+title = NULL, 
+title.size = 8, 
+lib.path = NULL
+){
+# AIM
+# display an empty ggplot2 plot with a text in the middle of the window (for instance to specify that no plot can be drawn)
+# ARGUMENTS
+# text: character string of the message to display
+# text.size: numeric value of the text size (in points)
+# title: character string of the graph title
+# title.size: numeric value of the title size (in points)
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
+# RETURN
+# an empty plot
+# REQUIRED PACKAGES
+# ggplot2
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# EXAMPLES
+### simple example
+# fun_gg_empty_graph(text = "NO GRAPH")
+### white page
+# fun_gg_empty_graph()
+### all the arguments
+# fun_gg_empty_graph(text = "NO GRAPH", text.size = 8, title = "GRAPH1", title.size = 10, lib.path = NULL)
+# DEBUGGING
+# text = "NO GRAPH" ; text.size = 12 ; title = "GRAPH1" ; title.size = 8 ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if( ! is.null(text)){
+tempo <- fun_check(data = text, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(title)){
+tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = title.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# package checking
+fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
+# end package checking
+# main code
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0
+# no need loop part
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggplot())
+if( ! is.null(text)){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(data = data.frame(x = 1, y = 1, stringsAsFactors = TRUE), ggplot2::aes(x = x, y = y, label = text), size = text.size))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_void())
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+plot.title = ggplot2::element_text(size = title.size) # stronger than text
+))
+suppressWarnings(print(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))))
+}
+
+
+################ Graphic extraction
+
+
+######## fun_trim() #### display values from a quantitative variable and trim according to defined cut-offs
+
+# Add name of the variable in the graph
+# not max and min for boxplot but 1.5IQR
+fun_trim <- function(
+data, 
+displayed.nb = NULL, 
+single.value.display = FALSE, 
+trim.method = "", 
+trim.cutoffs = c(0.05, 
+0.975), 
+interval.scale.disp = TRUE, 
+down.space = 0.75, 
+left.space = 0.75, 
+up.space = 0.3, 
+right.space = 0.25, 
+orient = 1, 
+dist.legend = 0.37, 
+box.type = "l", 
+amplif.label = 1.25, 
+amplif.axis = 1.25, 
+std.x.range = TRUE, 
+std.y.range = TRUE, 
+cex.pt = 0.2, 
+col.box = hsv(0.55, 
+0.8, 
+0.8), 
+x.nb.inter.tick = 4, 
+y.nb.inter.tick = 0, 
+tick.length = 1, 
+sec.tick.length = 0.75, 
+corner.text = "", 
+amplif.legend = 1, 
+corner.text.size = 0.75, 
+trim.return = FALSE
+){
+# AIM
+# trim and display values from a numeric vector or matrix
+# plot 4 graphs: stripchart of values, stripchart of rank of values, histogram and normal QQPlot
+# different kinds of intervals are displayed on the top of graphes to facilitate the analysis of the variable and a trimming setting
+# the trimming interval chosen is displayed on top of graphs
+# both trimmed and not trimmed values are returned in a list
+# ARGUMENTS
+# data: values to plot (either a numeric vector or a numeric matrix)
+# displayed.nb: number of values displayed. If NULL, all the values are displayed. Otherwise, if the number of values is over displayed.nb, then displayed.nb values are displayed after random selection
+# single.value.display: provide the 4 graphs if data is made of a single (potentially repeated value)? If FALSE, an empty graph is displayed if data is made of a single (potentially repeated value). And the return list is made of NULL compartments
+# trim.method: Write "" if not required. write "mean.sd" if mean +/- sd has to be displayed as a trimming interval (only recommanded for normal distribution). Write "quantile" to display a trimming interval based on quantile cut-offs. No other possibility allowed. See trim.cutoffs below
+# trim.cutoffs: 2 values cutoff for the trimming interval displayed, each value between 0 and 1. Not used if trim.method == "".The couple of values c(lower, upper) represents the lower and upper boundaries of the trimming interval (in proportion), which represent the interval of distribution kept (between 0 and 1). Example: trim.cutoffs = c(0.05, 0.975). What is strictly kept for the display is ]lower , upper[, boundaries excluded. Using the "mean.sd" method, 0.025 and 0.975 represent 95% CI which is mean +/- 1.96 * sd
+# interval.scale.disp: display sd and quantiles intervals on top of graphs ?
+# down.space: lower vertical margin (in inches, mai argument of par())
+# left.space: left horizontal margin (in inches, mai argument of par())
+# up.space: upper vertical margin between plot region and grapical window (in inches, mai argument of par())
+# right.space: right horizontal margin (in inches, mai argument of par())
+# orient: scale number orientation (las argument of par()). 0, always parallel to the axis; 1, always horizontal; 2, always perpendicular to the axis; 3, always vertical
+# dist.legend: numeric value that moves axis legends away in inches (first number of mgp argument of par() but in inches thus / 0.2)
+# box.type: bty argument of par(). Either "o", "l", "7", "c", "u", "]", the resulting box resembles the corresponding upper case letter. A value of "n" suppresses the box
+# amplif.label: increase or decrease the size of the text in legends
+# amplif.axis: increase or decrease the size of the scale numbers in axis
+# std.x.range: standard range on the x-axis? TRUE (no range extend) or FALSE (4% range extend). Controls xaxs argument of par() (TRUE is xaxs = "i", FALSE is xaxs = "r")
+# std.y.range: standard range on the y-axis? TRUE (no range extend) or FALSE (4% range extend). Controls yaxs argument of par() (TRUE is yaxs = "i", FALSE is yaxs = "r")
+# cex.pt: size of points in stripcharts (in inches, thus cex.pt will be thereafter / 0.2)
+# col.box: color of boxplot
+# x.nb.inter.tick: number of secondary ticks between main ticks on x-axis (only if not log scale). Zero means non secondary ticks
+# y.nb.inter.tick: number of secondary ticks between main ticks on y-axis (only if not log scale). Zero means non secondary ticks
+# tick.length: length of the ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc. 0 means no tick
+# sec.tick.length: length of the secondary ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
+# corner.text: text to add at the top right corner of the window
+# amplif.legend: increase or decrease the size of the text of legend
+# corner.text.size: positive numeric. Increase or decrease the size of the text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
+# trim.return: return the trimmed and non trimmed values? NULL returned for trimmed and non trimmed values if trim.method == ""
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# RETURN
+# a list containing:
+# $trim.method: correspond to trim.method above
+# $trim.cutoffs: correspond to trim.cutoffs above
+# $real.trim.cutoffs: the two boundary values (in the unit of the numeric vector or numeric matrix analyzed). NULL 
+# $trimmed.values: the values outside of the trimming interval as defined in trim.cutoffs above
+# $kept.values: the values inside the trimming interval as defined in trim.cutoffs above
+# EXAMPLES
+# fun_trim(data = c(1:100, 1:10), displayed.nb = NULL, single.value.display = FALSE, trim.method = "mean.sd", trim.cutoffs = c(0.05, 0.975), interval.scale.disp = TRUE, down.space = 0.75, left.space = 0.75, up.space = 0.3, right.space = 0.25, orient = 1, dist.legend = 0.37, box.type = "l", amplif.label = 1.25, amplif.axis = 1.25, std.x.range = TRUE, std.y.range = TRUE, cex.pt = 0.2, col.box = hsv(0.55, 0.8, 0.8), x.nb.inter.tick = 4, y.nb.inter.tick = 0, tick.length = 0.5, sec.tick.length = 0.3, corner.text = "", amplif.legend = 1, corner.text.size = 0.75, trim.return = TRUE)
+# DEBUGGING
+# data = c(1:100, 1:10) ; displayed.nb = NULL ; single.value.display = FALSE ; trim.method = "quantile" ; trim.cutoffs = c(0.05, 0.975) ; interval.scale.disp = TRUE ; down.space = 1 ; left.space = 1 ; up.space = 0.5 ; right.space = 0.25 ; orient = 1 ; dist.legend = 0.5 ; box.type = "l" ; amplif.label = 1 ; amplif.axis = 1 ; std.x.range = TRUE ; std.y.range = TRUE ; cex.pt = 0.1 ; col.box = hsv(0.55, 0.8, 0.8) ; x.nb.inter.tick = 4 ; y.nb.inter.tick = 0 ; tick.length = 0.5 ; sec.tick.length = 0.3 ; corner.text = "" ; amplif.legend = 1 ; corner.text.size = 0.75 ; trim.return = TRUE # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+# argument checking without fun_check()
+if( ! (all(class(data) == "numeric") | all(class(data) == "integer") | (all(class(data) %in% c("matrix", "array")) & base::mode(data) == "numeric"))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A NUMERIC VECTOR OR NUMERIC MATRIX")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking without fun_check()
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+if( ! is.null(displayed.nb)){
+tempo <- fun_check(data = displayed.nb, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(displayed.nb < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": displayed.nb ARGUMENT MUST BE A SINGLE INTEGER VALUE GREATER THAN 1 AND NOT: ", paste(displayed.nb, collapse = " "))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = single.value.display, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = trim.method, options = c("", "mean.sd", "quantile"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = trim.cutoffs, class = "vector", mode = "numeric", length = 2, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = interval.scale.disp, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = down.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = up.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = orient, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.type, options = c("o", "l", "7", "c", "u", "]", "n"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = amplif.label, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = amplif.axis, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = std.x.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = std.y.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = cex.pt, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = col.box, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.nb.inter.tick, class = "integer", length = 1, neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.nb.inter.tick, class = "integer", length = 1, neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = sec.tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = corner.text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = amplif.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = corner.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = trim.return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+if(all(is.na(data) | ! is.finite(data))){
+tempo.cat <- paste0("ERROR IN fun_trim FUNCTION\ndata ARGUMENT CONTAINS ONLY NA OR Inf")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end argument checking
+# main code
+if(all(class(data)%in% c("matrix", "array"))){
+data <- as.vector(data)
+}
+na.nb <- NULL
+if(any(is.na(data))){
+na.nb <- sum(c(is.na(data)))
+data <- data[ ! is.na(data)]
+}
+color.cut <- hsv(0.75, 1, 1) # color of interval selected
+col.mean <- hsv(0.25, 1, 0.8) # color of interval using mean+/-sd
+col.quantile <- "orange" # color of interval using quantiles
+quantiles.selection <- c(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.975, 0.99) # quantiles used in axis to help for choosing trimming cutoffs
+if(single.value.display == FALSE & length(unique(data)) == 1L){
+par(bty = "n", xaxt = "n", yaxt = "n", xpd = TRUE)
+plot(1, pch = 16, col = "white", xlab = "", ylab = "")
+text(x = 1, y = 1, paste0("No graphic displayed\nBecause data made of a single different value (", formatC(as.double(table(data))), ")"), cex = 2)
+output <- list(trim.method = NULL, trim.cutoffs = NULL, real.trim.cutoffs = NULL, trimmed.values = NULL, kept.values = NULL)
+}else{
+output <- list(trim.method = trim.method, trim.cutoffs = trim.cutoffs, real.trim.cutoffs = NULL, trimmed.values = NULL, kept.values = NULL)
+fun.rug <- function(sec.tick.length.f = sec.tick.length, x.nb.inter.tick.f = x.nb.inter.tick, y.nb.inter.tick.f = y.nb.inter.tick){
+if(x.nb.inter.tick.f > 0){
+inter.tick.unit <- (par("xaxp")[2] - par("xaxp")[1]) / par("xaxp")[3]
+par.ini <- par()[c("xpd", "tcl")]
+par(xpd = FALSE)
+par(tcl = -par()$mgp[2] * sec.tick.length.f) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
+suppressWarnings(rug(seq(par("xaxp")[1] - 10 * inter.tick.unit, par("xaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + x.nb.inter.tick.f)), ticksize = NA, side = 1)) # ticksize = NA to allow the use of par()$tcl value
+par(par.ini)
+rm(par.ini)
+}
+if(y.nb.inter.tick.f > 0){
+inter.tick.unit <- (par("yaxp")[2] - par("yaxp")[1]) / par("yaxp")[3]
+par.ini <- par()[c("xpd", "tcl")]
+par(xpd = FALSE)
+par(tcl = -par()$mgp[2] * sec.tick.length.f) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
+suppressWarnings(rug(seq(par("yaxp")[1] - 10 * inter.tick.unit, par("yaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + y.nb.inter.tick.f)), ticksize = NA, side = 2)) # ticksize = NA to allow the use of par()$tcl value
+par(par.ini)
+rm(par.ini)
+}
+}
+fun.add.cut <- function(data.f, trim.method.f = trim.method, trim.cutoffs.f = trim.cutoffs, color.cut.f = color.cut, return.f = FALSE){
+# DEBUGGING
+# data.f = data ; trim.method.f = "mean.sd"; trim.cutoffs.f = trim.cutoffs ; color.cut.f = color.cut ; return.f = TRUE
+real.trim.cutoffs.f <- NULL
+if(trim.method.f != ""){
+data.f <- sort(data.f)
+par.ini <- par()$xpd
+par(xpd = FALSE)
+if(trim.method.f == "mean.sd"){
+real.trim.cutoffs.f <- qnorm(trim.cutoffs.f, mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE))
+abline(v = qnorm(trim.cutoffs.f, mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), col = color.cut.f)
+segments(qnorm(trim.cutoffs.f[1], mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), par()$usr[4] * 0.75, qnorm(trim.cutoffs.f[2], mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), par()$usr[4] * 0.75, col = color.cut.f)
+}
+if(trim.method.f == "quantile"){
+real.trim.cutoffs.f <- quantile(data.f, probs = trim.cutoffs.f, type = 7, na.rm = TRUE)
+abline(v = quantile(data.f, probs = trim.cutoffs.f, type = 7, na.rm = TRUE), col = color.cut.f)
+segments(quantile(data.f, probs = trim.cutoffs.f[1], type = 7, na.rm = TRUE), par()$usr[4] * 0.75, quantile(data.f, probs = trim.cutoffs.f[2], type = 7, na.rm = TRUE), par()$usr[4] * 0.75, col = color.cut.f)
+}
+par(par.ini)
+if(return.f == TRUE){
+trimmed.values.f <- data.f[data.f <= real.trim.cutoffs.f[1] | data.f >= real.trim.cutoffs.f[2]]
+kept.values.f <- data.f[data.f > real.trim.cutoffs.f[1] & data.f < real.trim.cutoffs.f[2]]
+}
+}else{
+real.trim.cutoffs.f <- NULL
+trimmed.values.f <- NULL
+kept.values.f <- NULL
+}
+if(return.f == TRUE){
+output <- list(trim.method = trim.method.f, trim.cutoffs = trim.cutoffs.f, real.trim.cutoffs = real.trim.cutoffs.f, trimmed.values = trimmed.values.f, kept.values = kept.values.f)
+return(output)
+}
+}
+fun.interval.scale.display <- function(data.f, col.quantile.f = col.quantile, quantiles.selection.f = quantiles.selection, col.mean.f = col.mean){ # intervals on top of graphs
+par.ini <- par()[c("mgp", "xpd")]
+par(mgp = c(0.25, 0.25, 0), xpd = NA)
+axis(side = 3, at = c(par()$usr[1], par()$usr[2]), labels = rep("", 2), col = col.quantile.f, lwd.ticks = 0)
+par(xpd = FALSE)
+axis(side = 3, at = quantile(as.vector(data.f), probs = quantiles.selection.f, type = 7, na.rm = TRUE), labels = quantiles.selection.f, col.axis = col.quantile.f, col = col.quantile.f)
+par(mgp = c(1.75, 1.75, 1.5), xpd = NA)
+axis(side = 3, at = c(par()$usr[1], par()$usr[2]), labels = rep("", 2), col = col.mean.f, lwd.ticks = 0)
+par(xpd = FALSE)
+axis(side = 3, at = m + s * qnorm(quantiles.selection.f), labels = formatC(round(qnorm(quantiles.selection.f), 2)), col.axis = col.mean.f, col = col.mean.f, lwd.ticks = 1)
+par(par.ini)
+}
+zone<-matrix(1:4, ncol=2)
+layout(zone)
+par(omi = c(0, 0, 1.5, 0), mai = c(down.space, left.space, up.space, right.space), las = orient, mgp = c(dist.legend / 0.2, 0.5, 0), xpd = FALSE, bty= box.type, cex.lab = amplif.label, cex.axis = amplif.axis, xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
+par(tcl = -par()$mgp[2] * tick.length) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
+if(is.null(displayed.nb)){
+sampled.data <- as.vector(data)
+if(corner.text == ""){
+corner.text <- paste0("ALL VALUES OF THE DATASET DISPLAYED")
+}else{
+corner.text <- paste0(corner.text, "\nALL VALUES OF THE DATASET DISPLAYED")
+}
+}else{
+if(length(as.vector(data)) > displayed.nb){
+sampled.data <- sample(as.vector(data), displayed.nb, replace = FALSE)
+if(corner.text == ""){
+corner.text <- paste0("WARNING: ONLY ", displayed.nb, " VALUES ARE DISPLAYED AMONG THE ", length(as.vector(data)), " VALUES OF THE DATASET ANALYZED")
+}else{
+corner.text <- paste0(corner.text, "\nWARNING: ONLY ", displayed.nb, " VALUES ARE DISPLAYED AMONG THE ", length(as.vector(data)), " VALUES OF THE DATASET ANALYZED")
+}
+}else{
+sampled.data <- as.vector(data)
+if(corner.text == ""){
+corner.text <- paste0("WARNING: THE DISPLAYED NUMBER OF VALUES PARAMETER ", deparse(substitute(displayed.nb)), " HAS BEEN SET TO ", displayed.nb, " WHICH IS ABOVE THE NUMBER OF VALUES OF THE DATASET ANALYZED -> ALL VALUES DISPLAYED")
+}else{
+corner.text <- paste0(corner.text, "\nWARNING: THE DISPLAYED NUMBER OF VALUES PARAMETER ", deparse(substitute(displayed.nb)), " HAS BEEN SET TO ", displayed.nb, " WHICH IS ABOVE THE NUMBER OF VALUES OF THE DATASET ANALYZED -> ALL VALUES DISPLAYED")
+}
+}
+}
+if( ! is.null(na.nb)){
+if(corner.text == ""){
+corner.text <- paste0("WARNING: NUMBER OF NA REMOVED IS ", na.nb)
+}else{
+corner.text <- paste0("WARNING: NUMBER OF NA REMOVED IS ", na.nb)
+}
+}
+stripchart(sampled.data, method="jitter", jitter=0.4, vertical=FALSE, ylim=c(0.5, 1.5), group.names = "", xlab = "Value", ylab="", pch=1, cex = cex.pt / 0.2)
+fun.rug(y.nb.inter.tick.f = 0)
+boxplot(as.vector(data), horizontal=TRUE, add=TRUE, boxwex = 0.4, staplecol = col.box, whiskcol = col.box, medcol = col.box, boxcol = col.box, range = 0, whisklty = 1)
+m <- mean(as.vector(data), na.rm = TRUE)
+s <- sd(as.vector(data), na.rm = TRUE)
+segments(m, 0.8, m, 1, lwd=2, col="red") # mean 
+segments(m -1.96 * s, 0.9, m + 1.96 * s, 0.9, lwd=1, col="red") # mean 
+graph.xlim <- par()$usr[1:2] # for hist() and qqnorm() below
+if(interval.scale.disp == TRUE){
+fun.interval.scale.display(data.f = data)
+if(corner.text == ""){
+corner.text <- paste0("MULTIPLYING FACTOR DISPLAYED (MEAN +/- SD) ON SCALES: ", paste(formatC(round(qnorm(quantiles.selection), 2))[-(1:(length(quantiles.selection) - 1) / 2)], collapse = ", "), "\nQUANTILES DISPLAYED ON SCALES: ", paste(quantiles.selection, collapse = ", "))
+}else{
+corner.text <- paste0(corner.text, "\nMULTIPLYING FACTOR DISPLAYED (MEAN +/- SD) ON SCALES: ", paste(formatC(round(qnorm(quantiles.selection), 2))[-(1:(length(quantiles.selection) - 1) / 2)], collapse = ", "), "\nQUANTILES DISPLAYED ON SCALES: ", paste(quantiles.selection, collapse = ", "))
+}
+}
+output.tempo <- fun.add.cut(data.f = data, return.f = TRUE) # to recover real.trim.cutoffs
+if(trim.return == TRUE){
+output <- output.tempo
+}
+par(xpd = NA)
+if(trim.method != ""){
+if(corner.text == ""){
+corner.text <- paste0("SELECTED CUT-OFFS (PROPORTION): ", paste(trim.cutoffs, collapse = ", "), "\nSELECTED CUT-OFFS: ", paste(output.tempo$real.trim.cutoffs, collapse = ", "))
+}else{
+corner.text <- paste0(corner.text, "\nSELECTED CUT-OFFS (PROPORTION): ", paste(trim.cutoffs, collapse = ", "), "\nSELECTED CUT-OFFS: ", paste(output.tempo$real.trim.cutoffs, collapse = ", "))
+}
+if(interval.scale.disp == TRUE){
+legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- 1.96sd", paste0("Trimming interval: ", paste0(trim.cutoffs, collapse = " , ")), "Mean +/- sd multiplying factor", "Quantile"), yjust = 0, lty=1, col=c(col.box, "red", color.cut, col.mean, col.quantile), bty="n", cex = amplif.legend)
+}else{
+legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- 1.96sd", paste0("Trimming interval: ", paste0(trim.cutoffs, collapse = " , "))), yjust = 0, lty=1, col=c(col.box, "red", color.cut), bty="n", cex = amplif.legend, y.intersp=1.25)
+}
+}else{
+if(interval.scale.disp == TRUE){
+legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- sd", "Mean +/- sd multiplying factor", "Quantile"), yjust = 0, lty=1, col=c(col.box, "red", col.mean, col.quantile), bty="n", cex = amplif.legend)
+}else{
+legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- sd"), yjust = 0, lty=1, col=c(col.box, "red"), bty="n", cex = amplif.legend, y.intersp=1.25)
+}
+}
+par(xpd = FALSE, xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
+hist(as.vector(data), main = "", xlim = graph.xlim, xlab = "Value", ylab="Density", col = grey(0.25)) # removed: breaks = seq(min(as.vector(data), na.rm = TRUE), max(as.vector(data), na.rm = TRUE), length.out = length(as.vector(data)) / 10)
+abline(h = par()$usr[3])
+fun.rug()
+if(interval.scale.disp == TRUE){
+fun.interval.scale.display(data.f = data)
+}
+fun.add.cut(data.f = data)
+par(xaxs = ifelse(std.x.range, "i", "r"))
+stripchart(rank(sampled.data), method="stack", vertical=FALSE, ylim=c(0.99, 1.3), group.names = "", xlab = "Rank of values", ylab="", pch=1, cex = cex.pt / 0.2)
+fun.rug(y.nb.inter.tick.f = 0)
+x.text <- par("usr")[2] + (par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1]) * (1 - par("plt")[2]) / 2
+y.text <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par()$omd[4] / 2) * ((par("plt")[4] - par("plt")[3])))) * (1 - par("omd")[4])) # BEWARE. Here in "(par()$omd[4] / 2", division by two because there are 2 graphs staked on the y axis, and not one
+par(xpd=NA)
+text(x = x.text, y = y.text, paste0(corner.text), adj=c(1, 1.1), cex = corner.text.size) # text at the topright corner
+par(xpd=FALSE)
+par(xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
+qqnorm(as.vector(sampled.data), main = "", datax = TRUE, ylab = "Value", pch = 1, col = "red", cex = cex.pt / 0.2)
+fun.rug()
+if(diff(quantile(as.vector(data), probs = c(0.25, 0.75), na.rm = TRUE)) != 0){ # otherwise, error generated
+qqline(as.vector(data), datax = TRUE)
+}
+if(interval.scale.disp == TRUE){
+fun.interval.scale.display(data.f = data)
+}
+fun.add.cut(data.f = data)
+}
+if(trim.return == TRUE){
+return(output)
+}
+}
+
+
+######## fun_segmentation() #### segment a dot cloud on a scatterplot and define the dots from another cloud outside the segmentation
+
+
+fun_segmentation <- function(
+data1, 
+x1, 
+y1, 
+x.range.split = NULL, 
+x.step.factor = 10, 
+y.range.split = NULL, 
+y.step.factor = 10, 
+error = 0, 
+data2 = NULL, 
+x2, 
+y2, 
+data2.pb.dot = "unknown", 
+xy.cross.kind = "&", 
+plot = FALSE, 
+graph.in.file = FALSE, 
+raster = TRUE, 
+warn.print = FALSE, 
+lib.path = NULL
+){
+# AIM
+# if data1 is a data frame corresponding to the data set of a scatterplot (with a x column for x-axis values and a y column for the y-axis column), then fun_segmentation() delimits a frame around the dots cloud using a sliding window set by x.range.split and x.step.factor to frame the top and bottom part of the cloud, and set by y.range.split and y.step.factor to frame the left and right part of the cloud
+# if a second data frame is provided, corresponding to the data set of a scatterplot (with a x column for x-axis values and a y column for the y-axis column), then fun_segmentation() defines the dots of this data frame, outside of the frame of the first data frame
+# WARNINGS
+# if dots from data2 look significant on the graph (outside the frame) but are not (not black on the last figure), this is probably because the frame is flat on the zero coordinate (no volume inside the frame at this position). Thus, no way to conclude that data2 dots here are significant. These dots are refered to as "unknown". The pb.dot argument deals with such dots
+# dots that are sometimes inside and outside the frame, depending on the sliding window, are treated differently: they are removed. Such dots are neither classified as "signif", "non signif" or "unknown", but as "inconsistent"
+# unknown dots are treated as finally significant, not significant, or unknown (data2.pb.dot argument) for each x-axis and y-axis separately. Then, the union or intersection of significant dots is performed (argument xy.cross.kind). See the example section
+# ARGUMENTS
+# data1: a data frame containing a column of x-axis values and a column of y-axis values
+# x1: character string of the data1 column name for x-axis (first column of data1 by default)
+# y1: character string of the data1 column name for y-axis (second column of data1 by default)
+# x.range.split: positive non null numeric value giving the number of interval on the x value range. if x.range is the range of the dots on the x-axis, then abs(diff(x.range) / x.range.split) gives the window size. Window size decreases when range.split increases. In unit of x-axis. Write NULL if not required. At least one of the x.range.split and y.range.split must be non NULL
+# x.step.factor: positive non null numeric value giving the shift step of the window. If x.step.factor = 1, no overlap during the sliding (when the window slides from position n to position n+1, no overlap between the two positions). If x.step.factor = 2, 50% of overlap (when the window slides from position n to position n+1, the window on position n+1 overlap 50% of the window when it was on position n)
+# y.range.split: same as x.range.split for the y-axis. At least one of the x.range.split and y.range.split must be non NULL
+# y.step.factor: same as x.step.factor for the y-axis
+# error: proportion (from 0 to 1) of false positives (i.e., proportion of dots from data1 outside of the frame). 0.05 means 5% of the dots from data1 outside of the frame
+# data2: a data frame containing a column of x-axis values and a column of y-axis values, for which outside dots of the data1 cloud has to be determined. Write NULL if not required
+# x2: character string of the data1 column name for x-axis (first column of data1 by default)
+# y2: character string of the data1 column name for y-axis (second column of data1 by default)
+# data2.pb.dot: unknown dots are explain in the warning section above. If "signif", then the unknown dots are finally considered as significant (outside the frame). If "not.signif", then the unknown dots are finally considered as non significant (inside the frame). If "unknown", no conclusion are drawn from these dots. See the examples below
+# xy.cross.kind: if data2 is non null and if both x.range.split and y.range.split are non null, which dots are finally significants? Write "&" for intersection of outside dots on x and on y. Write "|" for union of outside dots on x and on y. See the examples below
+# plot: logical. Print graphs that check the frame?
+# graph.in.file: logical. Graphs sent into a graphic device already opened? If FALSE, GUI are opened for each graph. If TRUE, no GUI are opended. The graphs are displayed on the current active graphic device. Ignored if plot is FALSE
+# raster: logical. Dots in raster mode? If FALSE, dots from each geom_point from geom argument are in vectorial mode (bigger pdf and long to display if millions of dots). If TRUE, dots from each geom_point from geom argument are in matricial mode (smaller pdf and easy display if millions of dots, but long to generate the layer). If TRUE, the region plot will be square to avoid a bug in fun_gg_point_rast(). If TRUE, solve the transparency problem with some GUI. Not considered if plot is FALSE
+# warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
+# lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL. Ignored if plot is FALSE
+# RETURN
+# several graphs if plot is TRUE
+# a list containing:
+# $data1.removed.row.nb: which rows have been removed due to NA; NaN, -Inf or Inf detection in x1 or y1 columns (NULL if no row removed)
+# $data1.removed.rows: removed rows (NULL if no row removed)
+# $data2.removed.row.nb: which rows have been removed due to NA; NaN, -Inf or Inf detection in x2 or y2 columns (NULL if no row removed)
+# $data2.removed.rows: removed rows (NULL if no row removed)
+# $hframe: x and y coordinates of the bottom and top frames for frame plotting (frame1 for the left step and frame2 for the right step)
+# $vframe: x and y coordinates of the left and right frames for frame plotting (frame1 for the down step and frame2 for the top step)
+# $data1.signif.dot: the significant dots of data1 (i.e., dots outside the frame). A good segmentation should not have any data1.signif.dot
+# $data1.non.signif.dot: the non significant dots of data1 (i.e., dots inside the frame)
+# $data1.inconsistent.dot: see the warning section above
+# $data2.signif.dot: the significant dots of data2 if non NULL (i.e., dots outside the frame)
+# $data2.non.signif.dot: the non significant dots of data2 (i.e., dots inside the frame)
+# $data2.unknown.dot: the problematic dots of data2 (i.e., data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots). Is systematically NULL except if argument data2.pb.dot = "unknown" and some data2 dots are in such situation. Modifying the segmentation x.range.split, x.step.factor, y.range.split, y.step.factor arguments can solve this problem
+# $data2.inconsistent.dot: see the warning section above
+# $axes: the x-axis and y-axis info
+# $warn: the warning messages. Use cat() for proper display. NULL if no warning
+# REQUIRED PACKAGES
+# ggplot2 if plot is TRUE
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# if plot is TRUE:
+# fun_pack()
+# fun_open()
+# fun_gg_palette()
+# fun_gg_scatter()
+# fun_gg_empty_graph()
+# fun_close()
+# EXAMPLES
+# example explaining the unknown and inconsistent dots, and the cross 
+
+# set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data1[5:7, 2] <- NA ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; data2[11:13, 1] <- Inf ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = 20, x.step.factor = 10, y.range.split = 23, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "not.signif", xy.cross.kind = "|", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
+# set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = NULL, x.step.factor = 10, y.range.split = 23, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "unknown", xy.cross.kind = "|", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
+# set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = 20, x.step.factor = 10, y.range.split = NULL, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "unknown", xy.cross.kind = "&", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
+# DEBUGGING
+# set.seed(1) ; data1 = data.frame(x = rnorm(50), y = rnorm(50), stringsAsFactors = TRUE) ; data1[5:7, 2] <- NA ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 5 ; x.step.factor = 10 ; y.range.split = 5 ; y.step.factor = 10 ; error = 0 ; data2 = data.frame(x = rnorm(50, 0, 2), y = rnorm(50, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "unknown" ; xy.cross.kind = "|" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
+# set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 20 ; x.step.factor = 10 ; y.range.split = 23 ; y.step.factor = 10 ; error = 0 ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "not.signif" ; xy.cross.kind = "|" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
+# set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 20 ; x.step.factor = 10 ; y.range.split = NULL ; y.step.factor = 10 ; error = 0 ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "unknown" ; xy.cross.kind = "&" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+ini.warning.length <- options()$warning.length
+warn <- NULL
+warn.count <- 0
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & length(data1) < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OF AT LEAST 2 COLUMNS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = x1, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (x1 %in% names(data1))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x1 ARGUMENT MUST BE A COLUMN NAME OF data1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & x1 %in% names(data1)){
+tempo <- fun_check(data = data1[, x1], data.name = "x1 COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = y1, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (y1 %in% names(data1))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y1 ARGUMENT MUST BE A COLUMN NAME OF data1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & y1 %in% names(data1)){
+tempo <- fun_check(data = data1[, y1], data.name = "y1 COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+if(is.null(x.range.split) & is.null(y.range.split)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE OF THE x.range.split AND y.range.split ARGUMENTS MUST BE NON NULL")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(x.range.split)){
+tempo <- fun_check(data = x.range.split, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & x.range.split < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.range.split ARGUMENT CANNOT BE LOWER THAN 1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+if( ! is.null(y.range.split)){
+tempo <- fun_check(data = y.range.split, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & y.range.split < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.range.split ARGUMENT CANNOT BE LOWER THAN 1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = x.step.factor, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & x.step.factor < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.step.factor ARGUMENT CANNOT BE LOWER THAN 1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = y.step.factor, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & y.step.factor < 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.step.factor ARGUMENT CANNOT BE LOWER THAN 1")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = error, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(data2)){
+if(is.null(x2) | is.null(y2)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x2 AND y2 ARGUMENTS CANNOT BE NULL IF data2 ARGUMENT IS NON NULL")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = data2, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & length(data2) < 2){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data2 ARGUMENT MUST BE A DATA FRAME OF AT LEAST 2 COLUMNS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(x2)){
+tempo <- fun_check(data = x2, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (x2 %in% names(data2))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x2 ARGUMENT MUST BE A COLUMN NAME OF data2")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & x2 %in% names(data2)){
+tempo <- fun_check(data = data2[, x2], data.name = "x2 COLUMN OF data2", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+}
+if( ! is.null(y2)){
+tempo <- fun_check(data = y2, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & ! (y2 %in% names(data2))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y2 ARGUMENT MUST BE A COLUMN NAME OF data2")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & y2 %in% names(data2)){
+tempo <- fun_check(data = data2[, y2], data.name = "y2 COLUMN OF data2", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+}
+}
+}
+if( ! is.null(data2)){
+tempo <- fun_check(data = data2.pb.dot, options = c("signif", "not.signif", "unknown"), length = 1, fun.name = function.name) ; eval(ee)
+}
+if( ! (is.null(x.range.split)) & ! (is.null(y.range.split))){
+tempo <- fun_check(data = xy.cross.kind, options = c("&", "|"), length = 1, fun.name = function.name) ; eval(ee)
+}
+tempo <- fun_check(data = plot, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & plot == TRUE){
+tempo <- fun_check(data = raster, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = graph.in.file, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & graph.in.file == TRUE & is.null(dev.list())){
+tempo.cat <- paste0("ERROR IN ", function.name, ": \ngraph.in.file PARAMETER SET TO TRUE BUT NO ACTIVE GRAPHIC DEVICE DETECTED")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo$problem == FALSE & graph.in.file == TRUE & ! is.null(dev.list())){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHS PRINTED IN THE CURRENT DEVICE (TYPE ", toupper(names(dev.cur())), ")")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# other required function checking
+if(plot == TRUE){
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_open", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_open() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_gg_palette", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_palette() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_gg_empty_graph", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_empty_graph() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_gg_scatter", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_scatter() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_close", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_close() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end other required function checking
+# package checking
+if(plot == TRUE){
+fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
+}
+# end package checking
+# main code
+# na and Inf detection and removal (done now to be sure of the correct length of categ)
+data1.removed.row.nb <- NULL
+data1.removed.rows <- NULL
+data2.removed.row.nb <- NULL
+data2.removed.rows <- NULL
+if(any(is.na(data1[, c(x1, y1)])) | any(is.infinite(data1[, x1])) | any(is.infinite(data1[, y1]))){
+tempo.na <- unlist(lapply(lapply(c(data1[c(x1, y1)]), FUN = is.na), FUN = which))
+tempo.inf <- unlist(lapply(lapply(c(data1[c(x1, y1)]), FUN = is.infinite), FUN = which))
+data1.removed.row.nb <- sort(unique(c(tempo.na, tempo.inf)))
+if(length(data1.removed.row.nb) > 0){
+data1.removed.rows <- data1[data1.removed.row.nb, ]
+}
+if(length(data1.removed.row.nb) == nrow(data1)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE NA, NaN, -Inf OR Inf DETECTED IN EACH ROW OF data1. FUNCTION CANNOT BE USED ON EMPTY DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(data1.removed.row.nb) > 0){
+data1 <- data1[-data1.removed.row.nb, ]
+}
+if(nrow(data1) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x1, y1), collapse = " "), " OF data1 AND CORRESPONDING ROWS REMOVED (SEE $data1.removed.row.nb AND $data1.removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x1, y1), collapse = " "), " OF data1. NO ROW REMOVED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data2)){
+if(any(is.na(data2[, c(x2, y2)])) | any(is.infinite(data2[, x2])) | any(is.infinite(data2[, y2]))){
+tempo.na <- unlist(lapply(lapply(c(data2[c(x2, y2)]), FUN = is.na), FUN = which))
+tempo.inf <- unlist(lapply(lapply(c(data2[c(x2, y2)]), FUN = is.infinite), FUN = which))
+data2.removed.row.nb <- sort(unique(c(tempo.na, tempo.inf)))
+if(length(data2.removed.row.nb) > 0){
+data2.removed.rows <- data2[data2.removed.row.nb, ]
+}
+if(length(data2.removed.row.nb) == nrow(data2)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE NA, NaN, -Inf OR Inf DETECTED IN EACH ROW OF data2. FUNCTION CANNOT BE USED ON EMPTY DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(data2.removed.row.nb) > 0){
+data2 <- data2[-data2.removed.row.nb, ]
+}
+if(nrow(data2) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x2, y2), collapse = " "), " OF data2 AND CORRESPONDING ROWS REMOVED (SEE $data2.removed.row.nb AND $data2.removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NO NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x2, y2), collapse = " "), " OF data2. NO ROW REMOVED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end na and Inf detection and removal (done now to be sure of the correct length of categ)
+# row annotation (dot number)
+# data1 <- data1[ ! duplicated(data1[, c(x1, y1)]), ] # do not remove the dots that have same x and y values, because they will have different dot number -> not the same position on the matrices (so true for symmetric matrices)
+data1 <- cbind(data1, DOT_NB = 1:nrow(data1), stringsAsFactors = TRUE)
+if( ! is.null(data2)){
+# data2 <- data2[ ! duplicated(data2[, c(x2, y2)]), ] # do not remove the dots that have same x and y values, because they will have different dot number -> not the same position on the matrices (so true for symmetric matrices)
+data2 <- cbind(data2, DOT_NB = 1:nrow(data2), stringsAsFactors = TRUE)
+}
+# end row annotation (dot number)
+
+
+
+
+# Method using x unit interval 
+# may be create vector of each column to increase speed
+x.data1.l <- NULL # x coord of the y upper and lower limits defined on the data1 cloud for left step line
+x.data1.r <- NULL # x coord of the y upper and lower limits defined on the data1 cloud for right step line
+y.data1.down.limit.l <- NULL # lower limit of the data1 cloud for left step line
+y.data1.top.limit.l <- NULL # upper limit of the data1 cloud for left step line
+y.data1.down.limit.r <- NULL # lower limit of the data1 cloud for right step line
+y.data1.top.limit.r <- NULL # upper limit of the data1 cloud for left step line
+if(any(data1[, x1] %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE x1 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+x.range <- range(data1[, x1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+if(suppressWarnings(any(x.range %in% c(Inf, -Inf)))){
+tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED x.range CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1[, y1] %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE y1 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+y.range <- range(data1[, y1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+if(suppressWarnings(any(x.range %in% c(Inf, -Inf)))){
+tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED y.range CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+x.range.plot <- range(data1[, x1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+y.range.plot <- range(data1[, y1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+if( ! is.null(data2)){
+if(any(data2[, x2] %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE data2 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE x2 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+x.range.plot <- range(data1[, x1], data2[, x2], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+if(any(data2[, y2] %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE data2 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE y2 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+y.range.plot <- range(data1[, y1], data2[, y2], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+}
+if(suppressWarnings(any(x.range.plot %in% c(Inf, -Inf)))){
+tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED x.range.plot CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 (AND data2?) ARGUMENTS ARE NA OR Inf ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(suppressWarnings(any(y.range.plot %in% c(Inf, -Inf)))){
+tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED y.range.plot CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 (AND data2?) ARGUMENTS ARE NA OR Inf ONLY")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(x.range.split)){
+# data.frame ordering to slide the window from small to big values + sliding window definition
+data1 <- data1[order(data1[, x1], na.last = TRUE), ]
+if( ! is.null(data2)){
+data2 <- data2[order(data2[, x2], na.last = TRUE), ]
+}
+x.win.size <- abs(diff(x.range) / x.range.split) # in unit of x-axis
+step <- x.win.size / x.step.factor
+# end data.frame ordering to slide the window from small to big values + sliding window definition
+# x-axis sliding and y-axis limits of the data1 cloud -> y significant data2
+loop.nb <- ceiling((diff(x.range) - x.win.size) / step) # x.win.size + n * step covers the x range if x.win.size + n * step >= diff(x.range), thus if n >= (diff(x.range) - x.win.size) / step 
+y.outside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are upper or lower than the frame
+y.inside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are not upper or lower than the frame
+y.data1.median <- median(data1[, y1], na.rm = TRUE) # will be used for sliding windows without data1 in it
+if( ! is.null(data2)){
+y.outside.data2.dot.nb <- integer() # vector that will contain the selected 1D coordinates (i.e., dots) of data2 that are upper or lower than the data1 frame
+y.inside.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are not upper or lower than the data1 frame
+y.unknown.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are problematic: data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots
+# recover data2 dots outside the range of data1
+if(any(data2[, x2] < x.range[1])){
+y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[data2[, x2] < x.range[1]])
+#tempo.warn & indicate the interval
+}
+if(any(data2[, x2] > x.range[2])){
+y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[data2[, x2] > x.range[2]])
+#tempo.warn & indicate the interval
+}
+# end recover data2 dots outside the range of data1
+}
+# loop.ini.time <- as.numeric(Sys.time())
+for(i1 in 0:(loop.nb + 1)){
+min.pos <- x.range[1] + step * i1 # lower position of the sliding window in data1
+max.pos <- min.pos + x.win.size # upper position of the sliding window in data1
+x.data1.l <- c(x.data1.l, min.pos, min.pos + step) # min.pos + step to make the steps
+x.data1.r <- c(x.data1.r, max.pos, max.pos + step) # max.pos + step to make the steps
+x.data1.dot.here <- data1[, x1] >= min.pos & data1[, x1] < max.pos # is there data1 dot present in the sliding window, considering the x axis?
+if( ! is.null(data2)){
+x.data2.dot.here <- data2[, x2] >= min.pos & data2[, x2] < max.pos # is there data2 dot present in the sliding window, considering the x axis?
+}
+# recover the data1 dots outside the frame
+if(any(x.data1.dot.here == TRUE)){
+tempo.y.data1.top.limit <- quantile(data1[x.data1.dot.here, y1], probs = 1 - error, na.rm = TRUE)
+tempo.y.data1.down.limit <- quantile(data1[x.data1.dot.here, y1], probs = 0 + error, na.rm = TRUE)
+y.data1.top.limit.l <- c(y.data1.top.limit.l, tempo.y.data1.top.limit, tempo.y.data1.top.limit)
+y.data1.down.limit.l <- c(y.data1.down.limit.l, tempo.y.data1.down.limit, tempo.y.data1.down.limit)
+y.data1.top.limit.r <- c(y.data1.top.limit.r, tempo.y.data1.top.limit, tempo.y.data1.top.limit)
+y.data1.down.limit.r <- c(y.data1.down.limit.r, tempo.y.data1.down.limit, tempo.y.data1.down.limit)
+y.data1.dot.signif <- ( ! ((data1[, y1] <= tempo.y.data1.top.limit) & (data1[, y1] >= tempo.y.data1.down.limit))) & x.data1.dot.here # is there data1 dot present in the sliding window, above or below the data1 limits, considering the y axis?
+y.data1.dot.not.signif <- x.data1.dot.here & ! y.data1.dot.signif
+y.outside.data1.dot.nb <- c(y.outside.data1.dot.nb, data1$DOT_NB[y.data1.dot.signif]) # recover the row number of data1
+y.outside.data1.dot.nb <- unique(y.outside.data1.dot.nb)
+y.inside.data1.dot.nb <- c(y.inside.data1.dot.nb, data1$DOT_NB[y.data1.dot.not.signif])
+y.inside.data1.dot.nb <- unique(y.inside.data1.dot.nb)
+}else{
+y.data1.top.limit.l <- c(y.data1.top.limit.l, y.data1.median, y.data1.median)
+y.data1.down.limit.l <- c(y.data1.down.limit.l, y.data1.median, y.data1.median)
+y.data1.top.limit.r <- c(y.data1.top.limit.r, y.data1.median, y.data1.median)
+y.data1.down.limit.r <- c(y.data1.down.limit.r, y.data1.median, y.data1.median)
+}
+# end recover the data1 dots outside the frame
+# recover the data2 dots outside the frame
+if( ! is.null(data2)){
+if(any(x.data1.dot.here == TRUE) & any(x.data2.dot.here == TRUE)){ 
+y.data2.dot.signif <- ( ! ((data2[, y2] <= tempo.y.data1.top.limit) & (data2[, y2] >= tempo.y.data1.down.limit))) & x.data2.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the y axis?
+y.data2.dot.not.signif <- x.data2.dot.here & ! y.data2.dot.signif
+y.outside.data2.dot.nb <- c(y.outside.data2.dot.nb, data2$DOT_NB[y.data2.dot.signif])
+y.outside.data2.dot.nb <- unique(y.outside.data2.dot.nb)
+y.inside.data2.dot.nb <- c(y.inside.data2.dot.nb, data2$DOT_NB[y.data2.dot.not.signif])
+y.inside.data2.dot.nb <- unique(y.inside.data2.dot.nb)
+}else if(any(x.data1.dot.here == FALSE) & any(x.data2.dot.here == TRUE)){ # problem: data2 dots in the the window but no data1 dots to generates the quantiles
+y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[x.data2.dot.here])
+y.unknown.data2.dot.nb <- unique(y.unknown.data2.dot.nb)
+#tempo.warn & indicate the interval
+
+
+
+
+# tempo.warn <- paste0("FROM FUNCTION ", function.name, ": THE [", round(min.pos, 3), " ; ", round(max.pos, 3), "] INTERVAL DOES NOT CONTAIN data1 X VALUES BUT CONTAINS data2 X VALUES WHICH CANNOT BE EVALUATED.\nTHE CONCERNED data2 ROW NUMBERS ARE:\n", paste(which(x.data1.dot.here == FALSE & x.data2.dot.here == TRUE), collapse = "\n"))
+# warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end recover the data2 dots outside the frame
+# if(any(i1 == seq(1, loop.nb, 500))){
+# loop.fin.time <- as.numeric(Sys.time()) # time of process end
+# cat(paste0("COMPUTATION TIME OF LOOP ", i1, " / ", loop.nb, ": ", as.character(lubridate::seconds_to_period(round(loop.fin.time - loop.ini.time))), "\n"))
+# }
+}
+if(max.pos < x.range[2]){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE SLIDING WINDOW HAS NOT REACHED THE MAX VALUE OF data1 ON THE X-AXIS: ", max.pos, " VERSUS ", x.range[2])
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+y.incon.data1.dot.nb.final <- unique(c(y.outside.data1.dot.nb[y.outside.data1.dot.nb %in% y.inside.data1.dot.nb], y.inside.data1.dot.nb[y.inside.data1.dot.nb %in% y.outside.data1.dot.nb])) # inconsistent dots: if a row number of y.inside.data1.dot.nb is present in y.outside.data1.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
+y.outside.data1.dot.nb.final <- y.outside.data1.dot.nb[ ! (y.outside.data1.dot.nb %in% y.incon.data1.dot.nb.final)] # inconsistent dots removed from the outside list
+y.inside.data1.dot.nb.final <- y.inside.data1.dot.nb[ ! (y.inside.data1.dot.nb %in% y.incon.data1.dot.nb.final)] # inconsistent dots removed from the inside list
+if( ! is.null(data2)){
+# if some unknown dots are also inside, and/or outside, they are put in the inside and/or outside. Ok, because then the intersection between inside and outside is treated -> inconsistent dots
+tempo.unknown.out <- y.unknown.data2.dot.nb[y.unknown.data2.dot.nb %in% y.outside.data2.dot.nb]
+y.outside.data2.dot.nb <- unique(c(y.outside.data2.dot.nb, tempo.unknown.out)) # if a row number of y.unknown.data2.dot.nb is present in y.outside.data2.dot.nb, it is put into outside
+tempo.unknown.in <- y.unknown.data2.dot.nb[y.unknown.data2.dot.nb %in% y.inside.data2.dot.nb]
+y.inside.data2.dot.nb <- unique(c(y.inside.data2.dot.nb, tempo.unknown.in)) # if a row number of y.unknown.data2.dot.nb is present in y.inside.data2.dot.nb, it is put into inside
+y.unknown.data2.dot.nb.final <- y.unknown.data2.dot.nb[ ! (y.unknown.data2.dot.nb %in% c(y.outside.data2.dot.nb, y.inside.data2.dot.nb))] # then dots also in inside and outside are remove from unknown
+y.incon.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb[y.outside.data2.dot.nb %in% y.inside.data2.dot.nb], y.inside.data2.dot.nb[y.inside.data2.dot.nb %in% y.outside.data2.dot.nb])) # inconsistent dots: if a row number of y.inside.data2.dot.nb is present in y.outside.data2.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
+y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb[ ! (y.outside.data2.dot.nb %in% y.incon.data2.dot.nb.final)] # inconsistent dots removed from the outside list
+y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb[ ! (y.inside.data2.dot.nb %in% y.incon.data2.dot.nb.final)] # inconsistent dots removed from the inside list
+}
+# end x-axis sliding and y-axis limits of the data1 cloud -> y significant data2
+}
+# end Method using x unit interval 
+
+
+
+
+# Method using y unit interval 
+y.data1.d <- NULL # y coord of the x upper and lower limits defined on the data1 cloud for down step line
+y.data1.t <- NULL # y coord of the x upper and lower limits defined on the data1 cloud for top step line
+x.data1.left.limit.d <- NULL # left limit of the data1 cloud for down step line
+x.data1.right.limit.d <- NULL # right limit of the data1 cloud for down step line
+x.data1.left.limit.t <- NULL # left limit of the data1 cloud for top step line
+x.data1.right.limit.t <- NULL # right limit of the data1 cloud for top step line
+if( ! is.null(y.range.split)){
+# data.frame ordering to slide the window from small to big values + sliding window definition
+data1 <- data1[order(data1[, y1], na.last = TRUE), ]
+if( ! is.null(data2)){
+data2 <- data2[order(data2[, y2], na.last = TRUE), ]
+}
+y.win.size <- abs(diff(y.range) / y.range.split) # in unit of y-axis
+step <- y.win.size / y.step.factor
+# end data.frame ordering to slide the window from small to big values + sliding window definition
+# y-axis sliding and x-axis limits of the data1 cloud -> x significant data2
+loop.nb <- ceiling((diff(y.range) - y.win.size) / step) # y.win.size + n * step covers the y range if y.win.size + n * step >= diff(y.range), thus if n >= (diff(y.range) - y.win.size) / step 
+x.outside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are upper or lower than the frame
+x.inside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are not upper or lower than the frame
+x.data1.median <- median(data1[, x1], na.rm = TRUE) # will be used for sliding window without data1 in it
+if( ! is.null(data2)){
+x.outside.data2.dot.nb <- integer() # vector that will contain the selected 1D coordinates (i.e., dots) of data2 that are upper or lower than the data1 frame
+x.inside.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are not upper or lower than the data1 frame
+x.unknown.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are problematic: data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots
+# recover data2 dots outside the range of data1
+if(any(data2[, y2] < y.range[1])){
+x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[data2[, y2] < y.range[1]])
+}
+if(any(data2[, y2] > y.range[2])){
+x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[data2[, y2] > y.range[2]])
+}
+# end recover data2 dots outside the range of data1
+}
+# loop.ini.time <- as.numeric(Sys.time())
+for(i1 in 0:(loop.nb + 1)){
+min.pos <- y.range[1] + step * i1 # lower position of the sliding window in data1
+max.pos <- min.pos + y.win.size # upper position of the sliding window in data1
+y.data1.d <- c(y.data1.d, min.pos, min.pos + step) # min.pos + step to make the steps
+y.data1.t <- c(y.data1.t, max.pos, max.pos + step) # max.pos + step to make the steps
+y.data1.dot.here <- data1[, y1] >= min.pos & data1[, y1] < max.pos # is there data1 dot present in the sliding window, considering the y axis?
+if( ! is.null(data2)){
+y.data2.dot.here <- data2[, y2] >= min.pos & data2[, y2] < max.pos # is there data2 dot present in the sliding window, considering the y axis?
+}
+# recover the data1 dots outside the frame
+if(any(y.data1.dot.here == TRUE)){
+tempo.x.data1.right.limit <- quantile(data1[y.data1.dot.here, x1], probs = 1 - error, na.rm = TRUE)
+tempo.x.data1.left.limit <- quantile(data1[y.data1.dot.here, x1], probs = 0 + error, na.rm = TRUE)
+x.data1.right.limit.d <- c(x.data1.right.limit.d, tempo.x.data1.right.limit, tempo.x.data1.right.limit)
+x.data1.left.limit.d <- c(x.data1.left.limit.d, tempo.x.data1.left.limit, tempo.x.data1.left.limit)
+x.data1.right.limit.t <- c(x.data1.right.limit.t, tempo.x.data1.right.limit, tempo.x.data1.right.limit)
+x.data1.left.limit.t <- c(x.data1.left.limit.t, tempo.x.data1.left.limit, tempo.x.data1.left.limit)
+x.data1.dot.signif <- ( ! ((data1[, x1] <= tempo.x.data1.right.limit) & (data1[, x1] >= tempo.x.data1.left.limit))) & y.data1.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the x axis?
+x.data1.dot.not.signif <- y.data1.dot.here & ! x.data1.dot.signif
+x.outside.data1.dot.nb <- c(x.outside.data1.dot.nb, data1$DOT_NB[x.data1.dot.signif]) # recover the row number of data1
+x.outside.data1.dot.nb <- unique(x.outside.data1.dot.nb)
+x.inside.data1.dot.nb <- c(x.inside.data1.dot.nb, data1$DOT_NB[x.data1.dot.not.signif])
+x.inside.data1.dot.nb <- unique(x.inside.data1.dot.nb)
+}else{
+x.data1.right.limit.d <- c(x.data1.right.limit.d, x.data1.median, x.data1.median)
+x.data1.left.limit.d <- c(x.data1.left.limit.d, x.data1.median, x.data1.median)
+x.data1.right.limit.t <- c(x.data1.right.limit.t, x.data1.median, x.data1.median)
+x.data1.left.limit.t <- c(x.data1.left.limit.t, x.data1.median, x.data1.median)
+}
+# end recover the data1 dots outside the frame
+# recover the data2 dots outside the frame
+if( ! is.null(data2)){
+if(any(y.data1.dot.here == TRUE) & any(y.data2.dot.here == TRUE)){ 
+x.data2.dot.signif <- ( ! ((data2[, x2] <= tempo.x.data1.right.limit) & (data2[, x2] >= tempo.x.data1.left.limit))) & y.data2.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the x axis?
+x.data2.dot.not.signif <- y.data2.dot.here & ! x.data2.dot.signif
+x.outside.data2.dot.nb <- c(x.outside.data2.dot.nb, data2$DOT_NB[x.data2.dot.signif])
+x.outside.data2.dot.nb <- unique(x.outside.data2.dot.nb)
+x.inside.data2.dot.nb <- c(x.inside.data2.dot.nb, data2$DOT_NB[x.data2.dot.not.signif])
+x.inside.data2.dot.nb <- unique(x.inside.data2.dot.nb)
+}else if(any(y.data1.dot.here == FALSE) & any(y.data2.dot.here == TRUE)){ # recover the data2 dots outside the range of the data1 cloud
+x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[y.data2.dot.here])
+x.unknown.data2.dot.nb <- unique(x.unknown.data2.dot.nb)
+
+
+
+# tempo.warn <- paste0("FROM FUNCTION ", function.name, ": THE [", round(min.pos, 3), " ; ", round(max.pos, 3), "] INTERVAL DOES NOT CONTAIN data1 Y VALUES BUT CONTAINS data2 Y VALUES WHICH CANNOT BE EVALUATED.\nTHE CONCERNED data2 ROW NUMBERS ARE:\n", paste(which(y.data1.dot.here == FALSE & y.data2.dot.here == TRUE), collapse = "\n"))
+# warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end recover the data2 dots outside the frame
+# if(any(i1 == seq(1, loop.nb, 500))){
+# loop.fin.time <- as.numeric(Sys.time()) # time of process end
+# cat(paste0("COMPUTATION TIME OF LOOP ", i1, " / ", loop.nb, ": ", as.character(lubridate::seconds_to_period(round(loop.fin.time - loop.ini.time))), "\n"))
+# }
+}
+if(max.pos < y.range[2]){
+tempo.cat <- paste0("ERROR IN ", function.name, ": THE SLIDING WINDOW HAS NOT REACHED THE MAX VALUE OF data1 ON THE Y-AXIS: ", max.pos, " VERSUS ", y.range[2])
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+x.incon.data1.dot.nb.final <- unique(c(x.outside.data1.dot.nb[x.outside.data1.dot.nb %in% x.inside.data1.dot.nb], x.inside.data1.dot.nb[x.inside.data1.dot.nb %in% x.outside.data1.dot.nb])) # inconsistent dots: if a row number of x.inside.data1.dot.nb is present in x.outside.data1.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
+x.outside.data1.dot.nb.final <- x.outside.data1.dot.nb[ ! (x.outside.data1.dot.nb %in% x.incon.data1.dot.nb.final)] # inconsistent dots removed from the outside list
+x.inside.data1.dot.nb.final <- x.inside.data1.dot.nb[ ! (x.inside.data1.dot.nb %in% x.incon.data1.dot.nb.final)] # inconsistent dots removed from the inside list
+if( ! is.null(data2)){
+# if some unknown dots are also inside, and/or outside, they are put in the inside and/or outside. Ok, because then the intersection between inside and outside is treated -> inconsistent dots
+tempo.unknown.out <- x.unknown.data2.dot.nb[x.unknown.data2.dot.nb %in% x.outside.data2.dot.nb]
+x.outside.data2.dot.nb <- unique(c(x.outside.data2.dot.nb, tempo.unknown.out)) # if a row number of x.unknown.data2.dot.nb is present in x.outside.data2.dot.nb, it is put into outside
+tempo.unknown.in <- x.unknown.data2.dot.nb[x.unknown.data2.dot.nb %in% x.inside.data2.dot.nb]
+x.inside.data2.dot.nb <- unique(c(x.inside.data2.dot.nb, tempo.unknown.in)) # if a row number of x.unknown.data2.dot.nb is present in x.inside.data2.dot.nb, it is put into inside
+x.unknown.data2.dot.nb.final <- x.unknown.data2.dot.nb[ ! (x.unknown.data2.dot.nb %in% c(x.outside.data2.dot.nb, x.inside.data2.dot.nb))] # then dots also in inside and outside are remove from unknown
+x.incon.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb[x.outside.data2.dot.nb %in% x.inside.data2.dot.nb], x.inside.data2.dot.nb[x.inside.data2.dot.nb %in% x.outside.data2.dot.nb])) # inconsistent dots: if a row number of x.inside.data2.dot.nb is present in x.outside.data2.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
+x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb[ ! (x.outside.data2.dot.nb %in% x.incon.data2.dot.nb.final)] # inconsistent dots removed from the outside list
+x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb[ ! (x.inside.data2.dot.nb %in% x.incon.data2.dot.nb.final)] # inconsistent dots removed from the inside list
+}
+# end y-axis sliding and x-axis limits of the data1 cloud -> x significant data2
+}
+# end Method using y unit interval 
+
+
+
+# recovering the frame coordinates
+hframe = rbind(
+data.frame(
+x = if(is.null(x.data1.l)){NULL}else{x.data1.l}, 
+y = if(is.null(x.data1.l)){NULL}else{y.data1.down.limit.l}, 
+kind = if(is.null(x.data1.l)){NULL}else{"down.frame1"},
+stringsAsFactors = TRUE
+), 
+data.frame(
+x = if(is.null(x.data1.r)){NULL}else{x.data1.r}, 
+y = if(is.null(x.data1.r)){NULL}else{y.data1.down.limit.r}, 
+kind = if(is.null(x.data1.r)){NULL}else{"down.frame2"},
+stringsAsFactors = TRUE
+), 
+data.frame(
+x = if(is.null(x.data1.l)){NULL}else{x.data1.l}, 
+y = if(is.null(x.data1.l)){NULL}else{y.data1.top.limit.l}, 
+kind = if(is.null(x.data1.l)){NULL}else{"top.frame1"},
+stringsAsFactors = TRUE
+), 
+data.frame(
+x = if(is.null(x.data1.r)){NULL}else{x.data1.r}, 
+y = if(is.null(x.data1.r)){NULL}else{y.data1.top.limit.r}, 
+kind = if(is.null(x.data1.r)){NULL}else{"top.frame2"},
+stringsAsFactors = TRUE
+), 
+stringsAsFactors = TRUE
+)
+vframe = rbind(
+data.frame(
+x = if(is.null(y.data1.d)){NULL}else{x.data1.left.limit.d}, 
+y = if(is.null(y.data1.d)){NULL}else{y.data1.d}, 
+kind = if(is.null(y.data1.d)){NULL}else{"left.frame1"},
+stringsAsFactors = TRUE
+), 
+data.frame(
+x = if(is.null(y.data1.t)){NULL}else{x.data1.left.limit.t}, 
+y = if(is.null(y.data1.t)){NULL}else{y.data1.t}, 
+kind = if(is.null(y.data1.t)){NULL}else{"left.frame2"},
+stringsAsFactors = TRUE
+), 
+data.frame(
+x = if(is.null(y.data1.d)){NULL}else{x.data1.right.limit.d}, 
+y = if(is.null(y.data1.d)){NULL}else{y.data1.d}, 
+kind = if(is.null(y.data1.d)){NULL}else{"right.frame1"},
+stringsAsFactors = TRUE
+),
+data.frame(
+x = if(is.null(y.data1.t)){NULL}else{x.data1.right.limit.t}, 
+y = if(is.null(y.data1.t)){NULL}else{y.data1.t}, 
+kind = if(is.null(y.data1.t)){NULL}else{"right.frame2"},
+stringsAsFactors = TRUE
+), 
+stringsAsFactors = TRUE
+)
+# end recovering the frame coordinates
+# recovering the dot coordinates
+data1.signif.dot <- NULL
+data1.non.signif.dot <- NULL
+data1.incon.dot <- NULL
+data2.signif.dot <- NULL
+data2.non.signif.dot <- NULL
+data2.unknown.dot <- NULL
+data2.incon.dot <- NULL
+if(( ! is.null(x.range.split)) & ( ! is.null(y.range.split))){
+# inconsistent dots recovery 
+if(length(unique(c(x.incon.data1.dot.nb.final, y.incon.data1.dot.nb.final))) > 0){
+data1.incon.dot <- data1[data1$DOT_NB %in% unique(c(x.incon.data1.dot.nb.final, y.incon.data1.dot.nb.final)), ] # if a dot in inconsistent in x or y -> classified as inconsistent (so unique() used)
+# removal of the inconsistent dot in the other classifications
+x.inside.data1.dot.nb.final <- x.inside.data1.dot.nb.final[ ! x.inside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+y.inside.data1.dot.nb.final <- y.inside.data1.dot.nb.final[ ! y.inside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+x.outside.data1.dot.nb.final <- x.outside.data1.dot.nb.final[ ! x.outside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+y.outside.data1.dot.nb.final <- y.outside.data1.dot.nb.final[ ! y.outside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+x.unknown.data1.dot.nb.final <- x.unknown.data1.dot.nb.final[ ! x.unknown.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+y.unknown.data1.dot.nb.final <- y.unknown.data1.dot.nb.final[ ! y.unknown.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
+# end removal of the inconsistent dot in the other classifications
+}
+if( ! is.null(data2)){
+if(length(unique(c(x.incon.data2.dot.nb.final, y.incon.data2.dot.nb.final))) > 0){
+data2.incon.dot <- data2[data2$DOT_NB %in% unique(c(x.incon.data2.dot.nb.final, y.incon.data2.dot.nb.final)), ]
+# removal of the inconsistent dot in the other classifications
+x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+x.unknown.data2.dot.nb.final <- x.unknown.data2.dot.nb.final[ ! x.unknown.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+y.unknown.data2.dot.nb.final <- y.unknown.data2.dot.nb.final[ ! y.unknown.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
+# end removal of the inconsistent dot in the other classifications
+}
+}
+# end inconsistent dots recovery 
+# unknown dots recovery 
+if( ! is.null(data2)){
+if(data2.pb.dot == "signif"){
+x.outside.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
+x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% x.unknown.data2.dot.nb.final] # remove x.unknown.data2.dot.nb.final from x.inside.data2.dot.nb.final
+y.outside.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
+y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% y.unknown.data2.dot.nb.final] # remove y.unknown.data2.dot.nb.final from y.inside.data2.dot.nb.final
+x.unknown.data2.dot.nb.final <- NULL
+y.unknown.data2.dot.nb.final <- NULL
+data2.unknown.dot <- NULL
+}else if(data2.pb.dot == "not.signif"){
+x.inside.data2.dot.nb.final <- unique(c(x.inside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
+x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% x.unknown.data2.dot.nb.final] # remove x.unknown.data2.dot.nb.final from x.outside.data2.dot.nb.final
+y.inside.data2.dot.nb.final <- unique(c(y.inside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
+y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% y.unknown.data2.dot.nb.final] # remove y.unknown.data2.dot.nb.final from y.outside.data2.dot.nb.final
+x.unknown.data2.dot.nb.final <- NULL
+y.unknown.data2.dot.nb.final <- NULL
+data2.unknown.dot <- NULL
+}else if(data2.pb.dot == "unknown"){
+if(length(unique(c(x.unknown.data2.dot.nb.final, y.unknown.data2.dot.nb.final))) > 0){
+data2.unknown.dot <- data2[data2$DOT_NB %in% unique(c(x.unknown.data2.dot.nb.final, y.unknown.data2.dot.nb.final)), ] # if a dot in unknown in x or y -> classified as unknown (so unique() used)
+x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove x.unknown.data2.dot.nb.final from x.outside.data2.dot.nb.final
+x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove x.unknown.data2.dot.nb.final from x.inside.data2.dot.nb.final
+y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove y.unknown.data2.dot.nb.final from y.outside.data2.dot.nb.final
+y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove y.unknown.data2.dot.nb.final from y.inside.data2.dot.nb.final
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end unknown dots recovery 
+# sign and non sign dot recovery
+if(xy.cross.kind == "|"){ # here the problem is to deal with significant dots depending on x and y. Thus I start with that, recover dots finally non significant in outside and put them in inside (when &), and remove from inside the dots in outside
+if(length(unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final))) > 0){
+tempo.outside <- unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final)) # union so unique() used
+tempo.inside <- unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final))
+tempo.inside <- tempo.inside[ ! tempo.inside %in% tempo.outside]
+data1.signif.dot <- data1[data1$DOT_NB %in% tempo.outside, ]
+data1.non.signif.dot <- data1[data1$DOT_NB %in% tempo.inside, ]
+}else{
+data1.non.signif.dot <- data1[unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
+}
+}else if(xy.cross.kind == "&"){
+if(sum(x.outside.data1.dot.nb.final %in% y.outside.data1.dot.nb.final) > 0){ # that is intersection
+tempo.outside <- unique(x.outside.data1.dot.nb.final[x.outside.data1.dot.nb.final %in% y.outside.data1.dot.nb.final]) # intersection
+tempo.outside.removed <- unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final))[ ! unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final)) %in% tempo.outside]
+tempo.inside <- unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final))
+data1.signif.dot <- data1[data1$DOT_NB %in% tempo.outside, ]
+data1.non.signif.dot <- data1[data1$DOT_NB %in% tempo.inside, ]
+}else{
+data1.non.signif.dot <- data1[unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(data2)){
+if(xy.cross.kind == "|"){ # here the problem is to deal with significant dots depending on x and y. Thus I start with that, recover dots finally non significant in outside and put them in inside (when &), and remove from inside the dots in outside
+if(length(unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final))) > 0){
+tempo.outside <- unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final)) # union so unique() used
+tempo.inside <- unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final))
+tempo.inside <- tempo.inside[ ! tempo.inside %in% tempo.outside]
+data2.signif.dot <- data2[data2$DOT_NB %in% tempo.outside, ]
+data2.non.signif.dot <- data2[data2$DOT_NB %in% tempo.inside, ]
+}else{
+data2.non.signif.dot <- data2[unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
+}
+}else if(xy.cross.kind == "&"){
+if(sum(x.outside.data2.dot.nb.final %in% y.outside.data2.dot.nb.final) > 0){ # that is intersection
+tempo.outside <- unique(x.outside.data2.dot.nb.final[x.outside.data2.dot.nb.final %in% y.outside.data2.dot.nb.final]) # intersection
+tempo.outside.removed <- unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final))[ ! unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final)) %in% tempo.outside]
+tempo.inside <- unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final))
+data2.signif.dot <- data2[data2$DOT_NB %in% tempo.outside, ]
+data2.non.signif.dot <- data2[data2$DOT_NB %in% tempo.inside, ]
+}else{
+data2.non.signif.dot <- data2[unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end sign and non sign dot recovery
+}else if(( ! is.null(x.range.split)) & is.null(y.range.split)){
+# inconsistent dots recovery 
+if(length(y.incon.data1.dot.nb.final) > 0){
+data1.incon.dot <- data1[data1$DOT_NB %in% y.incon.data1.dot.nb.final, ]
+}
+if( ! is.null(data2)){
+if(length(y.incon.data2.dot.nb.final) > 0){
+data2.incon.dot <- data2[data2$DOT_NB %in% y.incon.data2.dot.nb.final, ]
+}
+}# end inconsistent dots recovery 
+# unknown dots recovery 
+if( ! is.null(data2)){
+if(data2.pb.dot == "signif"){
+y.outside.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
+}else if(data2.pb.dot == "not.signif"){
+y.inside.data2.dot.nb.final <- unique(c(y.inside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
+}else if(data2.pb.dot == "unknown"){
+if(length(y.unknown.data2.dot.nb.final) > 0){
+data2.unknown.dot <- data2[data2$DOT_NB %in% y.unknown.data2.dot.nb.final, ]
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 6")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end unknown dots recovery 
+# sign and non sign dot recovery
+if(length(y.outside.data1.dot.nb.final) > 0){
+data1.signif.dot <- data1[data1$DOT_NB %in% y.outside.data1.dot.nb.final, ]
+}
+if(length(y.inside.data1.dot.nb.final) > 0){
+data1.non.signif.dot <- data1[data1$DOT_NB %in% y.inside.data1.dot.nb.final, ]
+}
+if( ! is.null(data2)){
+if(length(y.outside.data2.dot.nb.final) > 0){
+data2.signif.dot <- data2[data2$DOT_NB %in% y.outside.data2.dot.nb.final, ]
+}
+if(length(y.inside.data2.dot.nb.final) > 0){
+data2.non.signif.dot <- data2[data2$DOT_NB %in% y.inside.data2.dot.nb.final, ]
+}
+}
+# end sign and non sign dot recovery
+}else if(is.null(x.range.split) & ( ! is.null(y.range.split))){
+# inconsistent dots recovery 
+if(length(x.incon.data1.dot.nb.final) > 0){
+data1.incon.dot <- data1[data1$DOT_NB %in% x.incon.data1.dot.nb.final, ]
+}
+if( ! is.null(data2)){
+if(length(x.incon.data2.dot.nb.final) > 0){
+data2.incon.dot <- data2[data2$DOT_NB %in% x.incon.data2.dot.nb.final, ]
+}
+}# end inconsistent dots recovery 
+# unknown dots recovery 
+if( ! is.null(data2)){
+if(data2.pb.dot == "signif"){
+x.outside.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
+}else if(data2.pb.dot == "not.signif"){
+x.inside.data2.dot.nb.final <- unique(c(x.inside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
+}else if(data2.pb.dot == "unknown"){
+if(length(x.unknown.data2.dot.nb.final) > 0){
+data2.unknown.dot <- data2[data2$DOT_NB %in% x.unknown.data2.dot.nb.final, ]
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 7")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end unknown dots recovery 
+# sign and non sign dot recovery
+if(length(x.outside.data1.dot.nb.final) > 0){
+data1.signif.dot <- data1[data1$DOT_NB %in% x.outside.data1.dot.nb.final, ]
+}
+if(length(x.inside.data1.dot.nb.final) > 0){
+data1.non.signif.dot <- data1[data1$DOT_NB %in% x.inside.data1.dot.nb.final, ]
+}
+if( ! is.null(data2)){
+if(length(x.outside.data2.dot.nb.final) > 0){
+data2.signif.dot <- data2[data2$DOT_NB %in% x.outside.data2.dot.nb.final, ]
+}
+if(length(x.inside.data2.dot.nb.final) > 0){
+data2.non.signif.dot <- data2[data2$DOT_NB %in% x.inside.data2.dot.nb.final, ]
+}
+}
+# end sign and non sign dot recovery
+}
+# end recovering the dot coordinates
+# verif
+if(any(data1.signif.dot$DOT_NB %in% data1.non.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", FUNCTION.NAME, ": CODE INCONSISTENCY 8")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1.non.signif.dot$DOT_NB %in% data1.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", FUNCTION.NAME, ": CODE INCONSISTENCY 9")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1.signif.dot$DOT_NB %in% data1.incon.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 10")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1.incon.dot$DOT_NB %in% data1.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 11")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1.non.signif.dot$DOT_NB %in% data1.incon.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 12")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data1.incon.dot$DOT_NB %in% data1.non.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 13")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(data2)){
+if(any(data2.signif.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 14")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.non.signif.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 15")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.signif.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 16")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.unknown.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 17")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.signif.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 18")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.incon.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 19")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.non.signif.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 20")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.unknown.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 21")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.non.signif.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 22")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.incon.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 23")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.unknown.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 24")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(data2.incon.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 25")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end verif
+# plot
+# recovering the axes data whatever plot or not
+if(is.null(data2)){
+axes <- fun_gg_scatter(data1 = list(data1), x = list(x1), y = list(y1), categ = list(NULL), color = list(fun_gg_palette(2)[2]), geom = list("geom_point"), alpha = list(0.5), x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, plot = FALSE, return = TRUE)$axes
+}else{
+axes <- fun_gg_scatter(data1 = list(data1, data2), x = list(x1, x2), y = list(y1, y2), categ = list(NULL, NULL), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1]), geom = list("geom_point", "geom_point"), alpha = list(0.5, 0.5), x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, plot = FALSE, return = TRUE)$axes
+}
+# end recovering the axes data whatever plot or not
+if(plot == TRUE){
+# add a categ for plot legend
+tempo.df.name <- c("data1", "data1.signif.dot", "data1.incon.dot", "data2", "data2.signif.dot", "data2.unknown.dot", "data2.incon.dot")
+tempo.class.name <- c("data1", "data1", "data1", "data2", "data2", "data2", "data2")
+for(i2 in 1:length(tempo.df.name)){
+if( ! is.null(get(tempo.df.name[i2], env = sys.nframe(), inherit = FALSE))){
+assign(tempo.df.name[i2], data.frame(get(tempo.df.name[i2], env = sys.nframe(), inherit = FALSE), kind = tempo.class.name[i2]),
+stringsAsFactors = TRUE)
+}
+}
+# end add a categ for plot legend
+if(( ! is.null(x.range.split)) & ( ! is.null(y.range.split))){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe), x = list(x1, "x", "x"), y = list(y1, "y", "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data1.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe, data1.signif.dot), x = list(x1, "x", "x", x1), y = list(y1, "y", "y", y1), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
+}
+if( ! is.null(data1.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe, data1.incon.dot), x = list(x1, "x", "x", x1), y = list(y1, "y", "y", y1), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
+}
+if( ! is.null(data2)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, hframe , vframe), x = list(x1, x2, "x", "x"), y = list(y1, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data2.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
+}
+if( ! is.null(data2.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
+}
+if( ! is.null(data2.unknown.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 12, title = "DATA2 + DATA2 UNKNOWN DOTS")
+}
+}
+}else if(( ! is.null(x.range.split)) & is.null(y.range.split)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe), x = list(x1, "x"), y = list(y1, "y"), categ = list("kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_path"), alpha = list(0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data1.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, data1.signif.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
+}
+if( ! is.null(data1.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, data1.incon.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
+}
+if( ! is.null(data2)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, hframe), x = list(x1, x2, "x"), y = list(y1, y2, "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data2.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
+}
+if( ! is.null(data2.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
+}
+if( ! is.null(data2.unknown.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 8, title = "DATA2 + DATA2 UNKNOWN DOTS")
+}
+}
+}else if(is.null(x.range.split) & ( ! is.null(y.range.split))){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe), x = list(x1, "x"), y = list(y1, "y"), categ = list("kind", "kind"), legend.name = list("DATASET", "VERT FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_path"), alpha = list(0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data1.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe, data1.signif.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "VERT FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
+}
+if( ! is.null(data1.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe, data1.incon.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "VERT FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
+}
+if( ! is.null(data2)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, vframe), x = list(x1, x2, "x"), y = list(y1, y2, "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(data2.signif.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
+}
+if( ! is.null(data2.incon.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
+}
+if( ! is.null(data2.unknown.dot)){
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
+if( ! is.null(tempo.graph$warn)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(graph.in.file == FALSE){
+fun_open(pdf = FALSE)
+}
+fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 8, title = "DATA2 + DATA2 UNKNOWN DOTS")
+}
+}
+}
+}
+# end plot
+if(warn.print == TRUE & ! is.null(warn)){
+options(warning.length = 8170)
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+tempo.list <- list(data1.removed.row.nb = data1.removed.row.nb, data1.removed.rows = data1.removed.rows, data2.removed.row.nb = data2.removed.row.nb, data2.removed.rows = data2.removed.rows, hframe = hframe, vframe = vframe, data1.signif.dot = data1.signif.dot, data1.non.signif.dot = data1.non.signif.dot, data1.inconsistent.dot = data1.incon.dot, data2.signif.dot = data2.signif.dot, data2.non.signif.dot = data2.non.signif.dot, data2.unknown.dot = data2.unknown.dot, data2.inconsistent.dot = data2.incon.dot, axes = axes, warn = warn)
+return(tempo.list)
+}
+
+
+################ Import
+
+
+######## fun_pack() #### check if R packages are present and import into the working environment
+
+
+fun_pack <- function(
+req.package, 
+load = FALSE, 
+lib.path = NULL
+){
+# AIM
+# check if the specified R packages are present in the computer and import them into the working environment
+# ARGUMENTS
+# req.package: character vector of package names to import
+# load: logical. Load the package into the environement (using library())? Interesting if packages are not in default folders or for checking the functions names of packages using search()
+# lib.path: optional character vector specifying the absolute pathways of the directories containing some of the listed packages in the req.package argument, if not in the default directories. Ignored if NULL
+# RETURN
+# nothing
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_pack(req.package = "nopackage")
+# fun_pack(req.package = "ggplot2")
+# fun_pack(req.package = "ggplot2", lib.path = "blablabla")
+# DEBUGGING
+# req.package = "ggplot2" ; lib.path = "C:/Program Files/R/R-3.5.1/library"
+# req.package = "serpentine" ; lib.path = "C:/users/gael/appdata/roaming/python/python36/site-packages"
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = req.package, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = load, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+if(is.null(lib.path)){
+lib.path <- .libPaths() # .libPaths(new = lib.path) # or .libPaths(new = c(.libPaths(), lib.path))
+}else{
+.libPaths(new = sub(x = lib.path, pattern = "/$|\\\\$", replacement = "")) # .libPaths(new = ) add path to default path. BEWARE: .libPaths() does not support / at the end of a submitted path. Thus check and replace last / or \\ in path
+lib.path <- .libPaths()
+}
+tempo <- NULL
+for(i1 in 1:length(req.package)){
+if( ! req.package[i1] %in% rownames(utils::installed.packages(lib.loc = lib.path))){
+tempo <- c(tempo, req.package[i1])
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0(
+"ERROR IN ", 
+function.name, 
+": PACKAGE", 
+ifelse(length(tempo) == 1L, paste0("\n\n", tempo, "\n\n"), paste0("S\n", paste(tempo, collapse = "\n"), "\n")), 
+"MUST BE INSTALLED IN", 
+ifelse(length(lib.path) == 1L, "", " ONE OF THESE FOLDERS"), 
+":\n", 
+paste(lib.path, collapse = "\n")
+)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(load == TRUE){
+for(i2 in 1:length(req.package)){
+suppressMessages(suppressWarnings(suppressPackageStartupMessages(library(req.package[i2], lib.loc = lib.path, quietly = TRUE, character.only = TRUE))))
+}
+}
+}
+
+
+######## fun_python_pack() #### check if python packages are present
+
+
+fun_python_pack <- function(
+req.package, 
+python.exec.path = NULL, 
+lib.path = NULL, 
+R.lib.path = NULL
+){
+# AIM
+# check if the specified python packages are present in the computer (no import)
+# WARNINGS
+# for python 3.7. Previous versions return an error "Error in sys$stdout$flush() : attempt to apply non-function"
+# ARGUMENTS
+# req.package: character vector of package names to import
+# python.exec.path: optional character vector specifying the absolute pathways of the executable python file to use (associated to the packages to use). If NULL, the reticulate::import_from_path() function used in fun_python_pack() seeks for an available version of python.exe, and then uses python_config(python_version, required_module, python_versions). But might not be the correct one for the lib.path parameter specified. Thus, it is recommanded to do not leave NULL, notably when using computing clusters
+# lib.path: optional character vector specifying the absolute pathways of the directories containing some of the listed packages in the req.package argument, if not in the default directories
+# R.lib.path: absolute path of the reticulate packages, if not in the default folders
+# RETURN
+# nothing
+# REQUIRED PACKAGES
+# reticulate
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# fun_pack()
+# EXAMPLES
+# example of error message
+# fun_python_pack(req.package = "nopackage")
+# example without error message (require the installation of the python serpentine package from https://github.com/koszullab/serpentine
+# fun_python_pack(req.package = "serpentine", python.exec.path = "C:/ProgramData/Anaconda3/python.exe", lib.path = "c:/programdata/anaconda3/lib/site-packages/")
+# another example of error message
+# fun_python_pack(req.package = "serpentine", lib.path = "blablabla")
+# DEBUGGING
+# req.package = "serpentine" ; python.exec.path = "C:/ProgramData/Anaconda3/python.exe" ; lib.path = "c:/programdata/anaconda3/lib/site-packages/" ; R.lib.path = NULL
+# req.package = "bad" ; lib.path = NULL ; R.lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(utils::find("fun_pack", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = req.package, class = "character", fun.name = function.name) ; eval(ee)
+if( ! is.null(python.exec.path)){
+tempo <- fun_check(data = python.exec.path, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(file.exists(python.exec.path))){ # separation to avoid the problem of tempo$problem == FALSE and python.exec.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": FILE PATH INDICATED IN THE python.exec.path ARGUMENT DOES NOT EXISTS:\n", paste(python.exec.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if( ! is.null(R.lib.path)){
+tempo <- fun_check(data = R.lib.path, class = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(R.lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and R.lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE R.lib.path ARGUMENT DOES NOT EXISTS:\n", paste(R.lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# package checking
+fun_pack(req.package = "reticulate", lib.path = R.lib.path)
+# end package checking
+# main code
+if(is.null(python.exec.path)){
+python.exec.path <- reticulate::py_run_string("
+import sys ;
+path_lib = sys.path
+") # python string
+python.exec.path <- python.exec.path$path_lib
+}
+if(is.null(lib.path)){
+lib.path <- reticulate::py_run_string("
+import sys ;
+path_lib = sys.path
+") # python string
+lib.path <- lib.path$path_lib
+}
+reticulate::use_python(Sys.which(python.exec.path), required = TRUE) # required to avoid the use of erratic python exec by reticulate::import_from_path()
+for(i1 in 1:length(req.package)){
+tempo.try <- vector("list", length = length(lib.path))
+for(i2 in 1:length(lib.path)){
+tempo.try[[i2]] <- suppressWarnings(try(reticulate::import_from_path(req.package[i1], path = lib.path[i2]), silent = TRUE))
+tempo.try[[i2]] <- suppressWarnings(try(reticulate::import_from_path(req.package[i1], path = lib.path[i2]), silent = TRUE)) # done twice to avoid the error message  about flushing present the first time but not the second time. see https://stackoverflow.com/questions/57357001/reticulate-1-13-error-in-sysstdoutflush-attempt-to-apply-non-function
+}
+if(all(sapply(tempo.try, FUN = grepl, pattern = "[Ee]rror"))){
+print(tempo.try)
+tempo.cat <- paste0("ERROR IN ", function.name, ": PACKAGE ", req.package[i1], " MUST BE INSTALLED IN THE MENTIONNED DIRECTORY:\n", paste(lib.path, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+} # else{
+# suppressMessages(suppressWarnings(suppressPackageStartupMessages(assign(req.package[i1], reticulate::import(req.package[i1]))))) # not required because try() already evaluates
+# }
+}
+}
+
+
+################ Print / Exporting results (text & tables)
+
+
+######## fun_report() #### print string or data object into output file
+
+
+fun_report <- function(
+data, 
+output = "results.txt", 
+path = "C:/Users/Gael/Desktop/", 
+overwrite = FALSE, 
+rownames.kept = FALSE, 
+vector.cat = FALSE, 
+noquote = TRUE, 
+sep = 2
+){
+# AIM
+# log file function: print a character string or a data object into a same output file
+# ARGUMENTS
+# data: object to print in the output file. If NULL, nothing is done, with no warning
+# output: name of the output file
+# path: location of the output file
+# overwrite: (logical) if output file already exists, defines if the printing is appended (default FALSE) or if the output file content is erased before printing (TRUE)
+# rownames.kept: (logical) defines whether row names have to be removed or not in small tables (less than length.rows rows)
+# vector.cat (logical). If TRUE print a vector of length > 1 using cat() instead of capture.output(). Otherwise (default FALSE) the opposite
+# noquote: (logical). If TRUE no quote are present for the characters
+# sep: number of separating lines after printed data (must be integer)
+# RETURN
+# nothing
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_report()
+# fun_report(data = 1:3, output = "results.txt", path = "C:/Users/Gael/Desktop", overwrite = TRUE, rownames.kept = FALSE, vector.cat = FALSE, noquote = FALSE, sep = 2)
+# DEBUGGING
+# data = 1:3 ; output = "results.txt" ; path = "C:/Users/Gael/Desktop" ; overwrite = TRUE ; rownames.kept = FALSE ; vector.cat = FALSE ; noquote = FALSE ; sep = 2 # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# argument checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = output, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & output == ""){
+tempo.cat <- paste0("ERROR IN ", function.name, ": output ARGUMENT AS \"\" DOES NOT CORRESPOND TO A VALID FILE NAME")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo <- fun_check(data = path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": path ARGUMENT DOES NOT CORRESPOND TO EXISTING DIRECTORY\n", paste(path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = overwrite, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = rownames.kept, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = vector.cat, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = noquote, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = sep, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# the 4 next lines are inactivated but kept because at a time, I might have a problem with data (solved with data = NULL). These 4 lines are just to know how to detect a missing argument. Important here because if data is not provided, print the code of the data function
+# arg.user.list <- as.list(match.call(expand.dots = FALSE))[-1] # recover all the arguments provided by the function user (excluding the argument with defaults values not provided by the user. Thus, it is really the list indicated by the user)
+# default.arg.list <- formals(fun = sys.function(sys.parent())) # list of all the arguments of the function with their default values (not the values of the user !). It seems that ls() as first line of the function provide the names of the arguments (empty, called, etc., or not)
+# arg.without.default.value <- sapply(default.arg.list, is.symbol) & sapply(sapply(default.arg.list, as.character), identical, "") # logical to detect argument without default values (these are typeof "symbol" and class "name" and empty character
+# if( ! all(names(default.arg.list)[arg.without.default.value] %in% names(arg.user.list))){ # test that the arguments with no null values are provided by the user
+# tempo.cat <- paste0("ERROR IN ", function.name, ": VALUE REQUIRED FOR THESE ARGUMENTS WITH NO DEFAULTS VALUES: ", paste(names(default.arg.list)[arg.without.default.value][ ! names(default.arg.list)[arg.without.default.value] %in% names(arg.user.list)], collapse = " "))
+# stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+# }
+# end argument checking
+# main code
+if( ! is.null(data)){
+if(all(class(data) == "data.frame") | all(class(data) == "table") | all(class(data) %in% c("matrix", "array"))){ # before R4.0.0, it was  all(class(data) %in% c("matrix", "data.frame", "table"))
+if(rownames.kept == FALSE & all(class(data) == "data.frame") & nrow(data) != 0 & nrow(data) <= 4){ # for data frames with nrows <= 4
+rownames.output.tables <- ""
+length.rows <- nrow(data)
+for(i in 1:length.rows){ # replace the rownames of the first 4 rows by increasing number of spaces (because identical row names not allowed in data frames). This method cannot be extended to more rows as the printed data frame is shifted on the right because of "big empty rownames"
+rownames.output.tables <- c(rownames.output.tables, paste0(rownames.output.tables[i]," ", collapse=""))
+}
+row.names(data) <- rownames.output.tables[1:length.rows]
+}else if(rownames.kept == FALSE & (all(class(data) == "table") | all(class(data) %in% c("matrix", "array")))){ # before R4.0.0, it was  & all(class(data) %in% c("matrix", "table"))
+rownames(data) <- rep("", nrow(data)) # identical row names allowed in matrices and tables
+}
+if(noquote == TRUE){
+utils::capture.output(noquote(data), file=paste0(path, "/", output), append = ! overwrite)
+}else{
+utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
+}
+}else if(is.vector(data) & all(class(data) != "list") & (length(data) == 1L | vector.cat == TRUE)){
+if(noquote == TRUE){
+cat(noquote(data), file= paste0(path, "/", output), append = ! overwrite)
+}else{
+cat(data, file= paste0(path, "/", output), append = ! overwrite)
+}
+}else if(all(base::mode(data) == "character")){ # characters (array, list, factor or vector with vector.cat = FALSE)
+if(noquote == TRUE){
+utils::capture.output(noquote(data), file=paste0(path, "/", output), append = ! overwrite)
+}else{
+utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
+}
+}else{ # other object (S4 for instance, which do not like noquote()
+utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
+}
+sep.final <- paste0(rep("\n", sep), collapse = "")
+write(sep.final, file= paste0(path, "/", output), append = TRUE) # add a sep
+}
+}
+
+
+######## fun_get_message() #### return error/warning/other messages of an expression (that can be exported)
+
+
+fun_get_message <- function(
+data, 
+kind = "error", 
+header = TRUE, 
+print.no = FALSE, 
+text = NULL, 
+env = NULL
+){
+# AIM
+# evaluate an instruction written between "" and return the first of the error, or warning or standard (non error non warning) messages if ever exist
+# using argument print.no = FALSE, return NULL if no message, which is convenient in some cases
+# WARNINGS
+# Only the first message is returned
+# Always use the env argument when fun_get_message() is used inside functions
+# The function does not prevent printing if print() is used inside the instruction tested. To prevent that, use tempo <- capture.output(error <- fun_get_message(data = "fun_check(data = 'a', class = mean, neg.values = FALSE, print = TRUE)")). The return of fun_get_message() is assigned into error and the printed messages are captured by capture.output() and assigned into tempo. See the examples
+# ARGUMENTS
+# data: character string to evaluate
+# kind: character string. Either "error" to get error messages, or "warning" to get warning messages, or "message" to get non error and non warning messages
+# header: logical. Add a header in the returned message?
+# print.no: logical. Print a message saying that no message reported?
+# text: character string added to the output message (even if no message exists and print.no is TRUE). Inactivated if header is FALSE
+# env: the name of an existing environment. NULL if not required
+# RETURN
+# the message or NULL if no message and print.no is FALSE
+# REQUIRED PACKAGES
+# none
+# REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
+# fun_check()
+# EXAMPLES
+# fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "error", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "warning", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "message", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "wilcox.test()", kind = "error", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "sum(1)", kind = "error", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "message('ahah')", kind = "error", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "message('ahah')", kind = "message", print.no = TRUE, text = "IN A")
+# fun_get_message(data = "ggplot2::ggplot(data = data.frame(X = 1:10, stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()", kind = "message", print.no = TRUE, text = "IN FUNCTION 1")
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_get_message(data = 'fun_gg_boxplot(data = obs1, y = "Time", categ = "Group1")', kind = "message", print.no = TRUE, text = "IN FUNCTION 1")
+# DEBUGGING
+# data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)" ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL # for function debugging
+# data = "sum(1)" ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL  # for function debugging
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; data = 'fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Group1")' ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL  # for function debugging
+# data = "message('ahah')" ; kind = "error" ; header = TRUE ; print.no = TRUE ; text = "IN A" ; env = NULL 
+# data = 'ggplot2::ggplot(data = data.frame(X = "a", stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()' ; kind = "message" ; header = TRUE ; print.no = FALSE ; text = NULL # for function debugging
+# data = 'ggplot2::ggplot(data = data.frame(X = "a", stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()' ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL # for function debugging
+# data = "emmeans::emmeans(object = emm.rg, specs = contrast.var)" ; kind = "message" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL # for function debugging
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+# end function name
+# required function checking
+if(length(utils::find("fun_check", mode = "function")) == 0L){
+tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# no need to use reserved words to avoid bugs, because it is local, and  exists("tempo.warning", inherit = FALSE), never use the scope
+# argument checking
+# argument checking with fun_check()
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = kind, options = c("error", "warning", "message"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = print.no, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = header, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(text)){
+tempo <- fun_check(data = text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+if( ! is.null(env)){
+tempo <- fun_check(data = env, class = "environment", fun.name = function.name) ; eval(ee) #
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# end argument checking with fun_check()
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument checking
+# main code
+pdf(file = NULL) # send plots into a NULL file, no pdf file created
+window.nb <- dev.cur()
+invisible(dev.set(window.nb))
+# last warning cannot be used because suppressWarnings() does not modify last.warning present in the base evironment (created at first warning in a new R session), or warnings() # to reset the warning history : unlockBinding("last.warning", baseenv()) ; assign("last.warning", NULL, envir = baseenv())
+output <- NULL
+tempo.error <- try(suppressMessages(suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))), silent = TRUE) # get error message, not warning or messages
+if(any(class(tempo.error) %in% c("gg", "ggplot"))){
+tempo.error <- try(suppressMessages(suppressWarnings(ggplot2::ggplot_build(tempo.error))), silent = TRUE)[1]
+}
+if(exists("tempo.error", inherit = FALSE) == TRUE){ # inherit = FALSE avoid the portee lexical and thus the declared word
+if( ! all(class(tempo.error) == "try-error")){ # deal with NULL and S4 objects. Old code:  ! (all(class(tempo.error) == "try-error") & any(grepl(x = tempo.error, pattern = "^Error|^error|^ERROR"))) but problem with S4 objects. Old code : if((length(tempo.error) > 0 & ! any(grepl(x = tempo.error, pattern = "^Error|^error|^ERROR"))) | (length(tempo.error) == 0) ){ but problem when tempo.error is a list but added this did not work: | ! all(class(tempo.error) == "character")
+tempo.error <- NULL
+}
+}else{
+tempo.error <- NULL
+}
+if(kind == "error" & ! is.null(tempo.error)){ # 
+if(header == TRUE){
+tempo.error[1] <- gsub(x = tempo.error[1], pattern = "^Error i|^error i|^ERROR I", replacement = "I")
+output <- paste0("ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.error[1]) #
+}else{
+output <- tempo.error[1] #
+}
+}else if(kind == "error" & is.null(tempo.error) & print.no == TRUE){
+output <- paste0("NO ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+}else if(kind != "error" & ( ! is.null(tempo.error)) & print.no == TRUE){
+output <- paste0("NO ", ifelse(kind == "warning", "WARNING", "STANDARD (NON ERROR AND NON WARNING)"), " MESSAGE BECAUSE OF ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+}else if(is.null(tempo.error)){
+fun.warning.capture <- function(expr){
+# from demo(error.catching) typed in the R console, coming from ?tryCatch
+# see also http://mazamascience.com/WorkingWithData/?p=912
+# return a character string or NULL
+# expr <- wilcox.test.default(c(1, 1, 3), c(1, 2, 4), paired = TRUE)
+W <- NULL
+w.handler <- function(w){ # warning handler
+W <<- w # send to the above env, i.e., the inside of the fun.warning.capture function
+invokeRestart("muffleWarning") # here w.handler() muffles all the warnings. See http://romainfrancois.blog.free.fr/index.php?post/2009/05/20/Disable-specific-warnings to muffle specific warnings and print others
+}
+output <- list(
+value = suppressMessages(withCallingHandlers(tryCatch(expr, error = function(e){e}), warning = w.handler)), # BEWARE: w.handler is a function written without (), like in other functions with FUN argument
+warning = W # processed by w.handler()
+)
+return(if(is.null(output$warning)){NULL}else{as.character(output$warning)})
+}
+tempo.warn <- fun.warning.capture(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))
+# warn.options.ini <- options()$warn ; options(warn = 1) ; tempo.warn <- utils::capture.output({tempo <- suppressMessages(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))}, type = "message") ; options(warn = warn.options.ini) # this recover warnings not messages and not errors but does not work in all enviroments
+tempo.message <- utils::capture.output({
+tempo <- suppressMessages(suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env})))
+if(any(class(tempo) %in% c("gg", "ggplot"))){
+tempo <- ggplot2::ggplot_build(tempo)
+}else{
+tempo <- suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))
+}
+}, type = "message") # recover messages not warnings and not errors
+if(kind == "warning" & ! is.null(tempo.warn)){
+if(length(tempo.warn) > 0){ # to avoid character(0)
+if( ! any(sapply(tempo.warn, FUN = "grepl", pattern = "() FUNCTION:$"))){
+tempo.warn <- paste(unique(tempo.warn), collapse = "\n") # if FALSE, means that the tested data is a special function. If TRUE, means that the data is a standard function. In that case, the output of capture.output() is two strings per warning messages: if several warning messages -> identical first string, which is removed in next messages by unique()
+}else{
+tempo.warn <- paste(tempo.warn, collapse = "\n")
+}
+if(header == TRUE){
+if(any(grepl(x = tempo.warn[[1]], pattern = "^simpleWarning i"))){
+tempo.warn[[1]] <- gsub(x = tempo.warn[[1]], pattern = "^Warning i", replacement = "I")
+}
+if(any(grepl(x = tempo.warn[[1]], pattern = "^Warning i"))){
+tempo.warn[[1]] <- gsub(x = tempo.warn[[1]], pattern = "^Warning i", replacement = "I")
+}
+output <- paste0("WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.warn) #
+}else{
+output <- tempo.warn #
+}
+}else{
+if(print.no == TRUE){
+output <- paste0("NO WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+} # no need else{} here because output is already NULL at first
+}
+}else if(kind == "warning" & is.null(tempo.warn) & print.no == TRUE){
+output <- paste0("NO WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+}else if(kind == "message" & exists("tempo.message", inherit = FALSE) == TRUE){ # inherit = FALSE avoid the portee lexical and thus the declared word
+if(length(tempo.message) > 0){ # if something is returned by capture.ouptput() (only in this env) with a length more than 1
+if(header == TRUE){
+output <- paste0("STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.message) #
+}else{
+output <- tempo.message #
+}
+}else{
+if(print.no == TRUE){
+output <- paste0("NO STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+} # no need else{} here because output is already NULL at first
+}
+}else if(kind == "message" & exists("tempo.message", inherit = FALSE) == FALSE & print.no == TRUE){
+output <- paste0("NO STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
+} # no need else{} here because output is already NULL at first
+} # no need else{} here because output is already NULL at first
+invisible(dev.off(window.nb)) # end send plots into a NULL file
+return(output) # do not use cat() because the idea is to reuse the message
+}
+
+
+
+
+
+# Error: class order not good when a class is removed due to NA
+# Error: line 136 in check 20201126 with add argument
+# Solve this: sometimes error messages can be more than the max display (8170). Thus, check every paste0("ERROR IN ", function.name, and trunck the message if to big. In addition, add at the begining of the warning message that it is too long and see the $warn output for complete message. Add also this into fun_scatter
+# add dot.shape ? See with available aesthetic layers
+# rasterise: https://cran.r-project.org/web/packages/ggrastr/vignettes/Raster_geoms.html
+# add horizontal argument and deal any conflict with vertical argument. Start with horizontal = NULL as default. If ! is.null() -> convert vertical if required
+
+fun_gg_boxplot <- function(
+data1, 
+y, 
+categ, 
+categ.class.order = NULL, 
+categ.color = NULL, 
+box.legend.name = NULL, 
+box.fill = FALSE, 
+box.width = 0.5, 
+box.space = 0.1, 
+box.line.size = 0.75, 
+box.notch = FALSE, 
+box.alpha = 1, 
+box.mean = TRUE, 
+box.whisker.kind = "std", 
+box.whisker.width = 0, 
+dot.color = grey(0.25), 
+dot.categ = NULL, 
+dot.categ.class.order = NULL, 
+dot.legend.name = NULL, 
+dot.tidy = FALSE, 
+dot.tidy.bin.nb = 50, 
+dot.jitter = 0.5, 
+dot.seed = 2, 
+dot.size = 3, 
+dot.alpha = 0.5, 
+dot.border.size = 0.5, 
+dot.border.color = NULL, 
+x.lab = NULL, 
+x.angle = 0, 
+y.lab = NULL, 
+y.lim = NULL, 
+y.log = "no", 
+y.tick.nb = NULL, 
+y.second.tick.nb = 1, 
+y.include.zero = FALSE, 
+y.top.extra.margin = 0.05, 
+y.bottom.extra.margin = 0.05, 
+stat.pos = "top", 
+stat.mean = FALSE, 
+stat.size = 4, 
+stat.dist = 5, 
+stat.angle = 0, 
+vertical = TRUE, 
+text.size = 12, 
+title = "", 
+title.text.size = 8, 
+legend.show = TRUE, 
+legend.width = 0.5, 
+article = TRUE, 
+grid = FALSE, 
+add = NULL, 
+return = FALSE, 
+return.ggplot = FALSE,
+return.gtable = TRUE,
+plot = TRUE, 
+warn.print = FALSE, 
+lib.path = NULL
+){
+# AIM
+# Plot ggplot2 boxplots + dots + means
+# For ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
+# WARNINGS
+# Rows containing NA in data1[, c(y, categ)] will be removed before processing, with a warning (see below)
+# Hinges are not computed like in the classical boxplot() function of R. See https://ggplot2.tidyverse.org/reference/geom_boxplot.html
+# To have a single box, please create a factor column with a single class and specify the name of this column in the categ argument. For a single set of grouped boxes, create a factor column with a single class and specify this column in categ argument as first element (i.e., as categ1, knowing that categ2 must also be specified in this situation). See categ argument below
+# The dot.alpha argument can alter the display of the color boxes when using pdf output
+# Size arguments (box.line.size, dot.size, dot.border.size, stat.size, text.size and title.text.size) are in mm. See Hadley comment in https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size. See also http://sape.inf.usi.ch/quick-reference/ggplot2/size). Unit object are not accepted, but conversion can be used (e.g., grid::convertUnit(grid::unit(0.2, "inches"), "mm", valueOnly = TRUE))
+# Display seems to be done twice on Windows devices (like a blink). However, no double plots on pdf devices. Thus, the blink remains mysterious
+# To remove boxes and have only dots, use box.alpha = 0
+# ARGUMENTS
+# data1: data frame containing one column of quantitative values (see the y argument below) and one or two columns of categories (see the categ argument below). Duplicated column names are not allowed
+# y: character string of the data1 column name for y-axis (column containing numeric values). Numeric values will be split according to the classes of the column names indicated in the categ argument to generate the boxes and will also be used to plot the dots
+# categ: vector of character strings of the data1 column name for categories (column of characters or factors). Must be either one or two column names. If a single column name (further referred to as categ1), then one box per class of categ1. If two column names (further referred to as categ1 and categ2), then one box per class of categ2, which form a group of boxes in each class of categ1. WARNING: no empty classes allowed. To have a single box, create a factor column with a single class and specify the name of this column in the categ argument (here, no categ2 in categ argument). For a single set of grouped boxes, create a factor column with a single class and specify this column in categ argument as first element (i.e., as categ1), in addition to the already used category (as categ2 in this situation)
+# categ.class.order: list indicating the order of the classes of categ1 and categ2 represented on the boxplot (the first compartment for categ1 and and the second for categ2). If categ.class.order == NULL, classes are represented according to the alphabetical order. Some compartments can be NULL and others not. See the categ argument for categ1 and categ2 description
+# categ.color: vector of color character string for box frames (see the categ argument for categ1 and categ2 description)
+# If categ.color == NULL, default colors of ggplot2, whatever categ1 and categ2
+# If categ.color is non-null and only categ1 in categ argument, categ.color can be either:
+# (1) a single color string. All the boxes will have this color, whatever the number of classes of categ1
+# (2) a vector of string colors, one for each class of categ1. Each color will be associated according to categ.class.order of categ1
+# (3) a vector or factor of string colors, like if it was one of the column of data1 data frame. WARNING: a single color per class of categ1 and a single class of categ1 per color must be respected
+# Color functions, like grey(), hsv(), etc., are also accepted
+# Positive integers are also accepted instead of character strings, as long as above rules about length are respected. Integers will be processed by fun_gg_palette() using the maximal integer value among all the integers in categ.color (see fun_gg_palette())
+# If categ.color is non-null and categ1 and categ2 are specified, all the rules described above will apply to categ2 instead of categ1 (colors will be determined for boxes inside a group of boxes)
+# box.legend.name: character string of the legend title. If box.legend.name is NULL, then box.legend.name <- categ1 if only categ1 is present, and box.legend.name <- categ2 if categ1 and categ2 are present in the categ argument. Write "" if no legend required. See the categ argument for categ1 and categ2 description
+# box.fill: logical. Fill the box? If TRUE, the categ.color argument will be used to generate filled boxplots (the box frames being black) as well as filled outlier dots (the dot border being controlled by the dot.border.color argument). If all the dots are plotted (argument dot.color other than NULL), they will be over the boxes. If FALSE, the categ.color argument will be used to color the box frames and the outlier dot borders. If all the dots are plotted, they will be beneath the boxes
+# box.width: single numeric value (from 0 to 1) of width of either boxes or group of boxes
+# When categ argument has a single categ1 element (i.e., separate boxes. See the categ argument for categ1 and categ2 description), then each class of categ1 is represented by a single box. In that case, box.width argument defines each box width, from 0 (no box width) to 1 (max box width), but also the space between boxes (the code uses 1 - box.width for the box spaces). Of note, xmin and xmax of the fun_gg_boxplot() output report the box boundaries (around x-axis unit 1, 2, 3, etc., for each box)
+# When categ argument has a two categ1 and categ2 elements (i.e., grouped boxes), box.width argument defines the width allocated for each set of grouped boxes, from 0 (no group width) to 1 (max group width), but also the space between grouped boxes (the code uses 1 - box.width for the spaces). Of note, xmin and xmax of the fun_gg_boxplot() output report the box boundaries (around x-axis unit 1, 2, 3, etc., for each set of grouped box)
+# box.space: single numeric value (from 0 to 1) indicating the box separation inside grouped boxes, when categ argument has a two categ1 and categ2 elements. 0 means no space and 1 means boxes shrunk to a vertical line. Ignored if categ argument has a single categ1 element
+# box.line.size: single numeric value of line width of boxes and whiskers in mm
+# box.notch: logical. Notched boxplot? It TRUE, display notched boxplot, notches corresponding approximately to the 95% confidence interval of the median (the notch interval is exactly 1.58 x Inter Quartile Range (IQR) / sqrt(n), with n the number of values that made the box). If notch intervals between two boxes do not overlap, it can be interpreted as significant median differences
+# box.alpha: single numeric value (from 0 to 1) of box transparency (full transparent to full opaque, respectively). To remove boxplots, use box.alpha = 0
+# box.mean: logical. Add mean value? If TRUE, a diamond-shaped dot, with the horizontal diagonal corresponding to the mean value, is displayed over each boxplot
+# box.whisker.kind: range of the whiskers. Either "no" (no whiskers), or "std" (length of each whisker equal to 1.5 x Inter Quartile Range (IQR)), or "max" (length of the whiskers up or down to the most distant dot)
+# box.whisker.width: single numeric value (from 0 to 1) of the whisker width, with 0 meaning no whiskers and 1 meaning a width equal to the box width
+# dot.color: vector of color character string ruling the dot colors and the dot display. See the example section below for easier understanding of the rules described here
+# If NULL, no dots plotted
+# If "same", the dots will have the same colors as the respective boxplots
+# Otherwise, as in the rule (1), (2) or (3) described in the categ.color argument, except that in the possibility (3), the rule "a single color per class of categ and a single class of categ per color", does not have to be respected (for instance, each dot can have a different color). Colors will also depend on the dot.categ argument. If dot.categ is NULL, then colors will be applied to each class of the last column name specified in categ. If dot.categ is non-NULL, colors will be applied to each class of the column name specified in dot.categ. See examples
+# dot.categ: optional single character string of a column name (further referred to as categ3) of the data1 argument. This column of data1 will be used to generate a legend for dots, in addition to the legend for boxes. See the dot.color argument for details about the way the legend is built using the two dot.categ and dot.color arguments. If NULL, no legend created and the colors of dots will depend on dot.color and categ arguments (as explained in the dot.color argument)
+# dot.categ.class.order: optional vector of character strings indicating the order of the classes of categ3 (see the dot.categ argument). If dot.categ is non-NULL and dot.categ.class.order is NULL, classes are displayed in the legend according to the alphabetical order. Ignored if dot.categ is NULL
+# dot.legend.name: optional character string of the legend title for categ3 (see the dot.categ argument). If dot.legend.name == NULL, dot.categ value is used (name of the column in data1). Write "" if no legend required. Ignored if dot.categ is NULL
+# dot.tidy: logical. Nice dot spreading? If TRUE, use the geom_dotplot() function for a nice representation. WARNING: change the true quantitative coordinates of dots (i.e., y-axis values for vertical display) because of binning. Thus, the gain in aestheticism is associated with a loss in precision that can be very important. If FALSE, dots are randomly spread on the qualitative axis, using the dot.jitter argument (see below) keeping the true quantitative coordinates
+# dot.tidy.bin.nb: positive integer indicating the number of bins (i.e., nb of separations) of the y.lim range. Each dot will then be put in one of the bin, with a diameter of the width of the bin. In other words, increase the number of bins to have smaller dots. Not considered if dot.tidy is FALSE
+# dot.jitter: numeric value (from 0 to 1) of random dot horizontal dispersion (for vertical display), with 0 meaning no dispersion and 1 meaning dispersion in the corresponding box width interval. Not considered if dot.tidy is TRUE
+# dot.seed: integer value that set the random seed. Using the same number will generate the same dot jittering. Write NULL to have different jittering each time the same instruction is run. Ignored if dot.tidy is TRUE
+# dot.size: numeric value of dot diameter in mm. Not considered if dot.tidy is TRUE
+# dot.alpha: numeric value (from 0 to 1) of dot transparency (full transparent to full opaque, respectively)
+# dot.border.size: numeric value of border dot width in mm. Write zero for no dot border. If dot.tidy is TRUE, value 0 remove the border and other values leave the border without size control (geom_doplot() feature)
+# dot.border.color: single character color string defining the color of the dot border (same color for all the dots, whatever their categories). If dot.border.color == NULL, the border color will be the same as the dot color. A single integer is also accepted instead of a character string, that will be processed by fun_gg_palette()
+# x.lab: a character string or expression for x-axis legend. If NULL, character string of categ1 (see the categ argument for categ1 and categ2 description)
+# x.angle: integer value of the text angle for the x-axis numbers, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
+# y.lab: a character string or expression for y-axis legend. If NULL, character string of the y argument
+# y.lim: 2 numeric values indicating the range of the y-axis. Order matters (for inverted axis). If NULL, the range of the x column name of data1 will be used. 
+# y.log: either "no", "log2" (values in the y argument column of the data1 data frame will be log2 transformed and y-axis will be log2 scaled) or "log10" (values in the y argument column of the data1 data frame will be log10 transformed and y-axis will be log10 scaled). WARNING: not possible to have horizontal boxes with a log axis, due to a bug in ggplot2 (see https://github.com/tidyverse/ggplot2/issues/881)
+# y.tick.nb: approximate number of desired values labeling the y-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if y.log is "no", then the number of labeling values is set by ggplot2. If NULL and if y.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the y.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for y.lim = c(9, 1200)). WARNING: if non-NULL and if y.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
+# y.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if y.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$y.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
+# y.include.zero: logical. Does y.lim range include 0? Ignored if y.log is "log2" or "log10"
+# y.top.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to y.lim. If different from 0, add the range of the axis multiplied by y.top.extra.margin (e.g., abs(y.lim[2] - y.lim[1]) * y.top.extra.margin) to the top of y-axis
+# y.bottom.extra.margin: idem as y.top.extra.margin but to the bottom of y-axis
+# stat.pos: add the median number above the corresponding box. Either NULL (no number shown), "top" (at the top of the plot region) or "above" (above each box)
+# stat.mean: logical. Display mean numbers instead of median numbers? Ignored if stat.pos is NULL
+# stat.size: numeric value of the stat font size in mm. Ignored if stat.pos is NULL
+# stat.dist: numeric value of the stat distance in percentage of the y-axis range (stat.dist = 5 means move the number displayed at 5% of the y-axis range). Ignored if stat.pos is NULL or "top"
+# stat.angle: integer value of the angle of stat, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
+# vertical: logical. Vertical boxes? WARNING: will be automatically set to TRUE if y.log argument is other than "no". Indeed, not possible to have horizontal boxes with a log axis, due to a bug in ggplot2 (see https://github.com/tidyverse/ggplot2/issues/881)
+# text.size: numeric value of the font size of the (1) axis numbers, (2) axis labels and (3) texts in the graphic legend (in mm)
+# title: character string of the graph title
+# title.text.size: numeric value of the title font size in mm
+# legend.show: logical. Show legend? Not considered if categ argument is NULL, because this already generate no legend, excepted if legend.width argument is non-NULL. In that specific case (categ is NULL, legend.show is TRUE and legend.width is non-NULL), an empty legend space is created. This can be useful when desiring graphs of exactly the same width, whatever they have legends or not
+# legend.width: single proportion (between 0 and 1) indicating the relative width of the legend sector (on the right of the plot) relative to the width of the plot. Value 1 means that the window device width is split in 2, half for the plot and half for the legend. Value 0 means no room for the legend, which will overlay the plot region. Write NULL to inactivate the legend sector. In such case, ggplot2 will manage the room required for the legend display, meaning that the width of the plotting region can vary between graphs, depending on the text in the legend
+# article: logical. If TRUE, use an article theme (article like). If FALSE, use a classic related ggplot theme. Use the add argument (e.g., add = "+ggplot2::theme_classic()" for the exact classic ggplot theme
+# grid: logical. Draw lines in the background to better read the box values? Not considered if article == FALSE (grid systematically present)
+# add: character string allowing to add more ggplot2 features (dots, lines, themes, facet, etc.). Ignored if NULL
+# WARNING: (1) the string must start with "+", (2) the string must finish with ")" and (3) each function must be preceded by "ggplot2::". Example: "+ ggplot2::coord_flip() + ggplot2::theme_bw()"
+# If the character string contains the "ggplot2::theme" string, then the article argument of fun_gg_boxplot() (see above) is ignored with a warning. In addition, some arguments can be overwritten, like x.angle (check all the arguments)
+# Handle the add argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
+# WARNING: the call of objects inside the quotes of add can lead to an error if the name of these objects are some of the fun_gg_boxplot() arguments. Indeed, the function will use the internal argument instead of the global environment object. Example article <- "a" in the working environment and add = '+ ggplot2::ggtitle(article)'. The risk here is to have TRUE as title. To solve this, use add = '+ ggplot2::ggtitle(get("article", envir = .GlobalEnv))'
+# return: logical. Return the graph parameters?
+# return.ggplot: logical. Return the ggplot object in the output list? Ignored if return argument is FALSE. WARNING: always assign the fun_gg_boxplot() function (e.g., a <- fun_gg_boxplot()) if return.ggplot argument is TRUE, otherwise, double plotting is performed. See $ggplot in the RETURN section below for more details
+# return.gtable: logical. Return the ggplot object as gtable of grobs in the output list? Ignored if plot argument is FALSE. Indeed, the graph must be plotted to get the grobs dispositions. See $gtable in the RETURN section below for more details
+# plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
+# warn.print: logical. Print warnings at the end of the execution? ? If FALSE, warning messages are never printed, but can still be recovered in the returned list. Some of the warning messages (those delivered by the internal ggplot2 functions) are not apparent when using the argument plot = FALSE
+# lib.path: character string indicating the absolute path of the required packages (see below). if NULL, the function will use the R library default folders
+# RETURN
+# A boxplot if plot argument is TRUE
+# A list of the graph info if return argument is TRUE:
+# $data: the initial data with graphic information added
+# $stat: the graphic statistics (mostly equivalent to ggplot_build()$data[[2]])
+# $removed.row.nb: which rows have been removed due to NA/Inf detection in y and categ columns (NULL if no row removed)
+# $removed.rows: removed rows (NULL if no row removed)
+# $plot: the graphic box and dot coordinates
+# $dots: dot coordinates
+# $main.box: coordinates of boxes
+# $median: median coordinates
+# $sup.whisker: coordinates of top whiskers (y for base and y.end for extremities)
+# $inf.whisker: coordinates of bottom whiskers (y for base and y.end for extremities)
+# $sup.whisker.edge: coordinates of top whisker edges (x and xend)
+# $inf.whisker.edge: coordinates of bottom whisker edges(x and xend)
+# $mean: diamond mean coordinates (only if box.mean argument is TRUE)
+# $stat.pos: coordinates of stat numbers (only if stat.pos argument is not NULL)
+# y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non-NULL or if y.log argument is different from "no")
+# y.second.tick.values: values of secondary ticks. NULL except if y.second.tick.nb argument is non-NULL or if y.log argument is different from "no")
+# $panel: the variable names used for the panels (NULL if no panels). WARNING: NA can be present according to ggplot2 upgrade to v3.3.0
+# $axes: the x-axis and y-axis info
+# $warn: the warning messages. Use cat() for proper display. NULL if no warning. WARNING: warning messages delivered by the internal ggplot2 functions are not apparent when using the argument plot = FALSE
+# $ggplot: ggplot object that can be used for reprint (use print(...$ggplot) or update (use ...$ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Of note, a non-NULL $ggplot in the output list is sometimes annoying as the manipulation of this list prints the plot
+# $gtable: gtable object that can be used for reprint (use gridExtra::grid.arrange(...$ggplot) or with additionnal grobs (see the grob decomposition in the examples). NULL if return.ggplot argument is FALSE. Contrary to $ggplot, a non-NULL $gtable in the output list is not annoying as the manipulation of this list does not print the plot
+# REQUIRED PACKAGES
+# ggplot2
+# gridExtra
+# lemon (in case of use in the add argument)
+# scales
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# fun_check()
+# fun_comp_1d()
+# fun_comp_2d()
+# fun_gg_just()
+# fun_gg_palette()
+# fun_inter_ticks()
+# fun_name_change()
+# fun_pack()
+# fun_round()
+# fun_scale()
+# EXAMPLE
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(20, 100, 10), rnorm(20, 200, 50), rnorm(20, 500, 60), rnorm(20, 100, 50)), Categ1 = rep(c("CAT", "DOG"), times = 40), Categ2 = rep(c("A", "B", "C", "D"), each = 20), Color1 = rep(c("coral", "lightblue"), times = 40), Color2 = rep(c("#9F2108", "#306100", "#007479", "#8500C0"), each = 20), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Categ1")
+# see http
+# DEBUGGING
+# set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Categ1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; set.seed(NULL) ; obs1$Time[1:10] <- NA ; data1 = obs1 ; y = "Time" ; categ = c("Categ1") ; categ.class.order = NULL ; categ.color = NULL ; box.legend.name = NULL ; box.fill = FALSE ; box.width = 0.5 ; box.space = 0.1 ; box.line.size = 0.75 ; box.notch = FALSE ; box.alpha = 1 ; box.mean = TRUE ; box.whisker.kind = "std" ; box.whisker.width = 0 ; dot.color = grey(0.25) ; dot.categ = NULL ; dot.categ.class.order = NULL ; dot.legend.name = NULL ; dot.tidy = FALSE ; dot.tidy.bin.nb = 50 ; dot.jitter = 0.5 ; dot.seed = 2 ; dot.size = 3 ; dot.alpha = 0.5 ; dot.border.size = 0.5 ; dot.border.color = NULL ; x.lab = NULL ; x.angle = 0 ; y.lab = NULL ; y.lim = NULL ; y.log = "no" ; y.tick.nb = NULL ; y.second.tick.nb = 1 ; y.include.zero = FALSE ; y.top.extra.margin = 0.05 ; y.bottom.extra.margin = 0.05 ; stat.pos = "top" ; stat.mean = FALSE ; stat.size = 4 ; stat.dist = 5 ; stat.angle = 0 ; vertical = TRUE ; text.size = 12 ; title = "" ; title.text.size = 8 ; legend.show = TRUE ; legend.width = 0.5 ; article = TRUE ; grid = FALSE ; add = NULL ; return = FALSE ; return.ggplot = FALSE ; return.gtable = TRUE ; plot = TRUE ; warn.print = FALSE ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_comp_2d", 
+"fun_gg_just", 
+"fun_gg_palette", 
+"fun_name_change", 
+"fun_pack", 
+"fun_check", 
+"fun_round", 
+"fun_scale",
+"fun_inter_ticks"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function")) == 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words to avoid bugs (names of dataframe columns used in this function)
+reserved.words <- c("categ.check", "categ.color", "dot.color", "dot.categ", "dot.max", "dot.min", "group", "PANEL", "group.check", "MEAN", "tempo.categ1", "tempo.categ2", "text.max.pos", "text.min.pos", "x", "x.y", "y", "y.check", "y_from.dot.max", "ymax", "tidy_group", "binwidth")
+# end reserved words to avoid bugs (used in this function)
+# arg with no default values
+mandat.args <- c(
+"data1", 
+"y", 
+"categ"
+)
+tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), ")")))
+if(any(tempo)){ # normally no NA for missing() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", "HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = categ, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if( ! is.null(categ.class.order)){
+tempo <- fun_check(data = categ.class.order, class = "list", fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = categ.class.order, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(box.legend.name)){
+tempo <- fun_check(data = box.legend.name, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = box.legend.name, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(categ.color)){
+tempo1 <- fun_check(data = categ.color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = categ.color, class = "factor", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.check.color <- fun_check(data = categ.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, neg.values = FALSE, fun.name = function.name)$problem
+if(tempo.check.color == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(any(categ.color == 0L, na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = categ.color, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = box.fill, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.space, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.line.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.notch, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.alpha, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.mean, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.whisker.kind, options = c("no", "std", "max"), length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = box.whisker.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(dot.color)){
+tempo1 <- fun_check(data = dot.color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = dot.color, class = "factor", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.check.color <- fun_check(data = dot.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, neg.values = FALSE, fun.name = function.name)$problem
+if(tempo.check.color == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(any(dot.color == 0L, na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.color, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(dot.categ)){
+tempo <- fun_check(data = dot.categ, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.categ, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(dot.categ.class.order)){
+tempo <- fun_check(data = dot.categ.class.order, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.categ.class.order, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(dot.legend.name)){
+tempo <- fun_check(data = dot.legend.name, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.legend.name, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = dot.tidy, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dot.tidy.bin.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if(dot.tidy.bin.nb == 0L){ # length and NA checked above
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.tidy.bin.nb ARGUMENT MUST BE A NON-NULL AND POSITVE INTEGER VALUE") # integer possible because dealt above
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+tempo <- fun_check(data = dot.jitter, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(dot.seed)){
+tempo <- fun_check(data = dot.seed, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.seed, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = dot.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dot.alpha, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = dot.border.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if( ! is.null(dot.border.color)){
+tempo1 <- fun_check(data = dot.border.color, class = "vector", mode = "character", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.border.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR STRING STARTING BY #, OR (2) A COLOR NAME GIVEN BY colors(), OR (3) AN INTEGER VALUE")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}else if(tempo1$problem == FALSE & tempo2$problem == TRUE){
+if( ! all(dot.border.color %in% colors() | grepl(pattern = "^#", dot.border.color), na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.border.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR STRING STARTING BY #, OR (2) A COLOR NAME GIVEN BY colors(), OR (3) AN INTEGER VALUE")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.border.color, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(x.lab)){
+tempo1 <- fun_check(data = x.lab, class = "expression", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = x.lab,  class = "vector", mode = "character", length = 1, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lab ARGUMENT MUST BE A SINGLE CHARACTER STRING OR EXPRESSION")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x.lab, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = x.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+if( ! is.null(y.lab)){
+tempo1 <- fun_check(data = y.lab, class = "expression", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = y.lab,  class = "vector", mode = "character", length = 1, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lab ARGUMENT MUST BE A SINGLE CHARACTER STRING OR EXPRESSION")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.lab, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(y.lim)){
+tempo <- fun_check(data = y.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if(any(is.infinite(y.lim))){ # normally no NA for is.infinite() output
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.lim, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = y.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(y.tick.nb)){
+tempo <- fun_check(data = y.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if(y.tick.nb < 0){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.tick.nb ARGUMENT MUST BE A NON NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(y.second.tick.nb)){
+tempo <- fun_check(data = y.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if(y.second.tick.nb <= 0){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.second.tick.nb ARGUMENT MUST BE A NON NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.second.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = y.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.top.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.bottom.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(stat.pos)){
+tempo <- fun_check(data = stat.pos, options = c("top", "above"), length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = stat.pos, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = stat.mean, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = stat.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = stat.dist, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = stat.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = vertical, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = legend.show, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(legend.width)){
+tempo <- fun_check(data = legend.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = legend.width, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = article, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = grid, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(add)){
+tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = add, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.ggplot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.gtable, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path), na.rm = TRUE)){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = lib.path, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if(any(arg.check) == TRUE){ # normally no NA
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"data1", 
+"y", 
+"categ", 
+"box.fill", 
+"box.width", 
+"box.space", 
+"box.line.size", 
+"box.notch", 
+"box.alpha", 
+"box.mean", 
+"box.whisker.kind", 
+"box.whisker.width", 
+# "dot.color", # inactivated because can be null
+"dot.tidy", 
+"dot.tidy.bin.nb", 
+"dot.jitter", 
+# "dot.seed", # inactivated because can be null
+"dot.size", 
+"dot.alpha", 
+"dot.border.size", 
+"x.angle", 
+"y.log", 
+# "y.second.tick.nb", # inactivated because can be null
+"y.include.zero", 
+"y.top.extra.margin", 
+"y.bottom.extra.margin", 
+# "stat.pos", # inactivated because can be null
+"stat.mean", 
+"stat.size", 
+"stat.dist", 
+"stat.angle", 
+"vertical", 
+"text.size", 
+"title", 
+"title.text.size", 
+"legend.show", 
+# "legend.width", # inactivated because can be null
+"article", 
+"grid", 
+"return", 
+"return.ggplot", 
+"return.gtable", 
+"plot", 
+"warn.print"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){# normally no NA with is.null()
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# see also Protocol 100-rev0 Parallelization in R.docx
+if(exists(".Random.seed", envir = .GlobalEnv)){ # if .Random.seed does not exists, it means that no random operation has been performed yet in any R environment
+tempo.random.seed <- .Random.seed
+on.exit(assign(".Random.seed", tempo.random.seed, env = .GlobalEnv))
+}else{
+on.exit(set.seed(NULL)) # inactivate seeding -> return to complete randomness
+}
+set.seed(dot.seed)
+# end code that protects set.seed() in the global environment
+# warning initiation
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+# end warning initiation
+# other checkings
+if(any(duplicated(names(data1)), na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDUPLICATED COLUMN NAMES OF data1 ARGUMENT NOT ALLOWED:\n", paste(names(data1)[duplicated(names(data1))], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! (y %in% names(data1))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny ARGUMENT MUST BE A COLUMN NAME OF data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+tempo <- fun_check(data = data1[, y], data.name = "y COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
+if(tempo$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny ARGUMENT MUST BE NUMERIC COLUMN IN data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(length(categ) > 2){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg ARGUMENT CANNOT HAVE MORE THAN 2 COLUMN NAMES OF data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! all(categ %in% names(data1))){ # all() without na.rm -> ok because categ cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg ARGUMENT MUST BE COLUMN NAMES OF data1. HERE IT IS:\n", paste(categ, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(length(dot.categ) > 1){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT CANNOT HAVE MORE THAN 1 COLUMN NAMES OF data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! all(dot.categ %in% names(data1))){ # all() without na.rm -> ok because dot.categ cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT MUST BE COLUMN NAMES OF data1. HERE IT IS:\n", paste(dot.categ, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# reserved word checking
+if(any(names(data1) %in% reserved.words, na.rm = TRUE)){
+if(any(duplicated(names(data1)), na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDUPLICATED COLUMN NAMES OF data1 ARGUMENT NOT ALLOWED:\n", paste(names(data1)[duplicated(names(data1))], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(dot.categ)){
+if(dot.categ %in% categ){
+reserved.words <- c(reserved.words, paste0(dot.categ, "_DOT")) # paste0(dot.categ, "_DOT") is added to the reserved words because in such situation, a new column will be added to data1 that is named paste0(dot.categ, "_DOT")
+}
+}
+tempo.output <- fun_name_change(names(data1), reserved.words)
+for(i2 in 1:length(tempo.output$ini)){ # a loop to be sure to take the good ones
+names(data1)[names(data1) == tempo.output$ini[i2]] <- tempo.output$post[i2]
+if(any(y == tempo.output$ini[i2])){ # any() without na.rm -> ok because y cannot be NA (tested above)
+y[y == tempo.output$ini[i2]] <- tempo.output$post[i2]
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN y ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN y ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# WARNING: names of y argument potentially replaced
+if(any(categ == tempo.output$ini[i2])){ # any() without na.rm -> ok because categ cannot be NA (tested above)
+categ[categ == tempo.output$ini[i2]] <- tempo.output$post[i2]
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN categ ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN categ ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# WARNING: names of categ argument potentially replaced
+if( ! is.null(dot.categ)){
+if(any(dot.categ == tempo.output$ini[i2])){ # any() without na.rm -> ok because dot.categ cannot be NA (tested above)
+dot.categ[dot.categ == tempo.output$ini[i2]] <- tempo.output$post[i2]
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN dot.categ ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN dot.categ ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# WARNING: names of dot.categ argument potentially replaced
+}
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") REGARDING COLUMN NAMES REPLACEMENT, THE NAMES\n", paste(tempo.output$ini, collapse = " "), "\nHAVE BEEN REPLACED BY\n", paste(tempo.output$post, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+if( ! (is.null(add) | is.null(tempo.output$ini))){
+if(grepl(x = add, pattern = paste(tempo.output$ini, collapse = "|"))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF COLUMN NAMES OF data1 IN THE add ARGUMENT STRING, THAT CORRESPOND TO RESERVED STRINGS FOR ", function.name, "\nCOLUMN NAMES HAVE TO BE CHANGED\nTHE PROBLEMATIC COLUMN NAMES ARE SOME OF THESE NAMES:\n", paste(tempo.output$ini, collapse = " "), "\nIN THE DATA FRAME OF data1 AND IN THE STRING OF add ARGUMENT, TRY TO REPLACE NAMES BY:\n", paste(tempo.output$post, collapse = " "), "\n\nFOR INFORMATION, THE RESERVED WORDS ARE:\n", paste(reserved.words, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+}
+if( ! (is.null(add))){
+if(any(sapply(X = arg.names, FUN = grepl, x = add), na.rm = TRUE)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NAMES OF ", function.name, " ARGUMENTS DETECTED IN THE add STRING:\n", paste(arg.names[sapply(X = arg.names, FUN = grepl, x = add)], collapse = "\n"), "\nRISK OF WRONG OBJECT USAGE INSIDE ", function.name)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end reserved word checking
+# verif of add
+if( ! is.null(add)){
+if( ! grepl(pattern = "^\\s*\\+", add)){ # check that the add string start by +
+tempo.cat <- paste0("ERROR IN ", function.name, "\nadd ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! grepl(pattern = "(ggplot2|lemon)\\s*::", add)){ #
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOR EASIER FUNCTION DETECTION, add ARGUMENT MUST CONTAIN \"ggplot2::\" OR \"lemon::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! grepl(pattern = ")\\s*$", add)){ # check that the add string finished by )
+tempo.cat <- paste0("ERROR IN ", function.name, "\nadd ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end verif of add
+# management of add containing facet
+facet.categ <- NULL
+if( ! is.null(add)){
+facet.check <- TRUE
+tempo <- unlist(strsplit(x = add, split = "\\s*\\+\\s*(ggplot2|lemon)\\s*::\\s*")) #
+tempo <- sub(x = tempo, pattern = "^facet_wrap", replacement = "ggplot2::facet_wrap")
+tempo <- sub(x = tempo, pattern = "^facet_grid", replacement = "ggplot2::facet_grid")
+tempo <- sub(x = tempo, pattern = "^facet_rep", replacement = "lemon::facet_rep")
+if(any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap"), na.rm = TRUE)){
+tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")])))
+facet.categ <- names(tempo1$params$facets)
+tempo.text <- "facet_wrap OR facet_rep_wrap"
+facet.check <- FALSE
+}else if(grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")){
+tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")])))
+facet.categ <- c(names(tempo1$params$rows), names(tempo1$params$cols))
+tempo.text <- "facet_grid OR facet_rep_grid"
+facet.check <- FALSE
+}
+if(facet.check == FALSE & ! all(facet.categ %in% names(data1))){ # WARNING: all(facet.categ %in% names(data1)) is TRUE when facet.categ is NULL # all() without na.rm -> ok because facet.categ cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF \"", tempo.text, "\" STRING IN THE add ARGUMENT BUT PROBLEM OF VARIABLE DETECTION (COLUMN NAMES OF data1)\nTHE DETECTED VARIABLES ARE:\n", paste(facet.categ, collapse = " "), "\nTHE data1 COLUMN NAMES ARE:\n", paste(names(data1), collapse = " "), "\nPLEASE REWRITE THE add STRING AND RERUN")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end management of add containing facet
+# conversion of categ columns in data1 into factors
+for(i1 in 1:length(categ)){
+tempo1 <- fun_check(data = data1[, categ[i1]], data.name = paste0("categ NUMBER ", i1, " OF data1"), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = data1[, categ[i1]], data.name = paste0("categ NUMBER ", i1, " OF data1"), class = "factor", na.contain = TRUE, fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\n", paste0("categ NUMBER ", i1, " OF data1"), " MUST BE A FACTOR OR CHARACTER VECTOR")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(tempo1$problem == FALSE){ # character vector
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN categ NUMBER ", i1, " IN data1, THE CHARACTER COLUMN HAS BEEN CONVERTED TO FACTOR, WITH LEVELS ACCORDING TO THE ALPHABETICAL ORDER")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+data1[, categ[i1]] <- factor(data1[, categ[i1]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+}
+# OK: all the categ columns of data1 are factors from here
+# end conversion of categ columns in data1 into factors
+
+
+
+# management of log scale and Inf removal
+if(any(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf  # normally no NA with is.finite0() and is.na()
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN THE ", y, " COLUMN OF THE data1 ARGUMENT AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+data1.ini <- data1 # strictly identical to data1 except that in data1 y is log converted if and only if y.log != "no"
+if(y.log != "no"){
+tempo1 <- ! is.finite(data1[, y]) # where are initial NA and Inf
+data1[, y] <- suppressWarnings(get(y.log)(data1[, y]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+if(any( ! (tempo1 | is.finite(data1[, y])))){ # normally no NA with is.finite
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN THE ", y, " COLUMN OF THE data1 ARGUMENT AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# Inf removal
+if(any(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf # normally no NA with is.finite
+removed.row.nb <- which(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))
+removed.rows <- data1.ini[removed.row.nb, ] # here data1.ini used to have the y = O rows that will be removed because of Inf creation after log transformation
+data1 <- data1[-removed.row.nb, ] #
+data1.ini <- data1.ini[-removed.row.nb, ] #
+}else{
+removed.row.nb <- NULL
+removed.rows <- data.frame(stringsAsFactors = FALSE)
+}
+# From here, data1 and data.ini have no more Inf
+# end Inf removal
+if(y.log != "no" & ! is.null(y.lim)){
+if(any(y.lim <= 0)){ # any() without na.rm -> ok because y.lim cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(any( ! is.finite(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}))){ # normally no NA with is.finite
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT RETURNS INF/NA WITH THE y.log ARGUMENT SET TO ", y.log, "\nAS SCALE COMPUTATION IS ", ifelse(y.log == "log10", "log10", "log2"), ":\n", paste(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(y.log != "no" & y.include.zero == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") y.log ARGUMENT SET TO ", y.log, " AND y.include.zero ARGUMENT SET TO TRUE -> y.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+y.include.zero <- FALSE
+}
+if(y.log != "no" & vertical == FALSE){
+vertical <- TRUE
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") BECAUSE OF A BUG IN ggplot2, CANNOT FLIP BOXES HORIZONTALLY WITH A Y.LOG SCALE -> vertical ARGUMENT RESET TO TRUE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end management of log scale and Inf removal
+# na detection and removal (done now to be sure of the correct length of categ)
+column.check <- unique(c(y, categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){dot.categ}, if( ! is.null(facet.categ)){facet.categ})) # dot.categ because can be a 3rd column of data1, categ.color and dot.color will be tested later
+if(any(is.na(data1[, column.check]))){ # data1 used here instead of data1.ini in case of new NaN created by log conversion (neg values) # normally no NA with is.na
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS OF data1 AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+for(i2 in 1:length(column.check)){
+if(any(is.na(data1[, column.check[i2]]))){ # normally no NA with is.na
+tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i2], " OF data1")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n", tempo.warn)))
+}
+}
+tempo <- unique(unlist(lapply(lapply(c(data1[column.check]), FUN = is.na), FUN = which)))
+removed.row.nb <- c(removed.row.nb, tempo) # removed.row.nb created to remove Inf
+removed.rows <- rbind(removed.rows, data1.ini[tempo, ], stringsAsFactors = FALSE) # here data1.ini used to have the non NA rows that will be removed because of NAN creation after log transformation (neg values for instance)
+column.check <- column.check[ ! column.check == y] # remove y to keep quali columns
+if(length(tempo) != 0){
+data1 <- data1[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
+data1.ini <- data1.ini[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers than the former
+for(i3 in 1:length(column.check)){
+if(any( ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]]), na.rm = TRUE)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i3], " OF data1, THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA/Inf REMOVAL (IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[, column.check[i3]])[ ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]])], collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+}
+count.categ <- 0
+for(i2 in 1:length(column.check)){
+if(column.check[i2] %in% categ){
+count.categ <- count.categ + 1
+}
+if(column.check[i2] == categ[count.categ]){
+categ.class.order[count.categ] <- list(levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])]) # remove the absent color in the character vector
+data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(categ.class.order[[count.categ]]))
+}
+if( ! is.null(dot.color) & ! is.null(dot.categ)){ # reminder : dot.categ cannot be a column name of categ anymore (because in that case dot.categ name is changed into "..._DOT"
+if(column.check[i2] == dot.categ){
+dot.categ.class.order <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
+data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(dot.categ.class.order))
+}
+}
+if(column.check[i2] %in% facet.categ){ # works if facet.categ == NULL this method should keep the order of levels when removing some levels
+tempo.levels <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(as.character(data1[, column.check[i2]]))]
+data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = tempo.levels)
+}
+}
+}
+# end na detection and removal (done now to be sure of the correct length of categ)
+# From here, data1 and data.ini have no more NA or NaN in y, categ, dot.categ (if dot.color != NULL) and facet.categ
+
+
+
+if( ! is.null(categ.class.order)){
+if(length(categ.class.order) != length(categ)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.class.order ARGUMENT MUST BE A LIST OF LENGTH EQUAL TO LENGTH OF categ\nHERE IT IS LENGTH: ", length(categ.class.order), " VERSUS ", length(categ))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+for(i3 in 1:length(categ.class.order)){
+if(is.null(categ.class.order[[i3]])){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE categ.class.order COMPARTMENT ", i3, " IS NULL. ALPHABETICAL ORDER WILL BE APPLIED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+data1[, categ[i3]] <- factor(as.character(data1[, categ[i3]])) # if already a factor, change nothing, if characters, levels according to alphabetical order
+categ.class.order[[i3]] <- levels(data1[, categ[i3]]) # character vector that will be used later
+}else{
+tempo <- fun_check(data = categ.class.order[[i3]], data.name = paste0("COMPARTMENT ", i3 , " OF categ.class.order ARGUMENT"), class = "vector", mode = "character", length = length(levels(data1[, categ[i3]])), fun.name = function.name) # length(data1[, categ[i1]) -> if data1[, categ[i1] was initially character vector, then conversion as factor after the NA removal, thus class number ok. If data1[, categ[i1] was initially factor, no modification after the NA removal, thus class number ok
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(any(duplicated(categ.class.order[[i3]]), na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i3, " OF categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(categ.class.order[[i3]], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! (all(categ.class.order[[i3]] %in% unique(data1[, categ[i3]]), na.rm = TRUE) & all(unique(data1[, categ[i3]]) %in% categ.class.order[[i3]], na.rm = TRUE))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i3, " OF categ.class.order ARGUMENT MUST BE CLASSES OF ELEMENT ", i3, " OF categ ARGUMENT\nHERE IT IS:\n", paste(categ.class.order[[i3]], collapse = " "), "\nFOR COMPARTMENT ", i3, " OF categ.class.order AND IT IS:\n", paste(unique(data1[, categ[i3]]), collapse = " "), "\nFOR COLUMN ", categ[i3], " OF data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+data1[, categ[i3]] <- factor(data1[, categ[i3]], levels = categ.class.order[[i3]]) # reorder the factor
+
+}
+names(categ.class.order)[i3] <- categ[i3]
+}
+}
+}else{
+categ.class.order <- vector("list", length = length(categ))
+tempo.categ.class.order <- NULL
+for(i2 in 1:length(categ.class.order)){
+categ.class.order[[i2]] <- levels(data1[, categ[i2]])
+names(categ.class.order)[i2] <- categ[i2]
+tempo.categ.class.order <- c(tempo.categ.class.order, ifelse(i2 != 1, "\n", ""), categ.class.order[[i2]])
+}
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR BOX ORDERING:\n", paste(tempo.categ.class.order, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# categ.class.order not NULL anymore (list)
+if(is.null(box.legend.name) & box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE box.legend.name SETTING IS NULL. NAMES OF categ WILL BE USED: ", paste(categ, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+box.legend.name <- categ[length(categ)] # if only categ1, then legend name of categ1, if length(categ) == 2L, then legend name of categ2
+}
+# box.legend.name not NULL anymore (character string)
+# management of categ.color
+if( ! is.null(categ.color)){
+# check the nature of color
+# integer colors into gg_palette
+tempo.check.color <- fun_check(data = categ.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem
+if(tempo.check.color == FALSE){
+# convert integers into colors
+categ.color <- fun_gg_palette(max(categ.color, na.rm = TRUE))[categ.color]
+}
+# end integer colors into gg_palette
+if( ! (all(categ.color %in% colors() | grepl(pattern = "^#", categ.color)))){ # check that all strings of low.color start by #, # all() without na.rm -> ok because categ.color cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors(): ", paste(unique(categ.color), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(is.na(categ.color)) & box.alpha != 0){ # normally no NA with is.na
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT CONTAINS NA")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end check the nature of color
+# check the length of color
+categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
+if(length(data1[, categ[categ.len]]) == length(levels(data1[, categ[categ.len]])) & length(categ.color) == length(data1[, categ[categ.len]])){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE NUMBER OF CLASSES OF THE COLUMN ", categ[categ.len], " THE NUMBER OF ROWS OF THIS COLUMN AND THE NUMBER OF COLORS OF THE categ.color ARGUMENT ARE ALL EQUAL. BOX COLORS WILL BE ATTRIBUTED ACCORDING THE LEVELS OF ", categ[categ.len], ", NOT ACCORDING TO THE ROWS OF ", categ[categ.len])
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if(length(categ.color) == length(levels(data1[, categ[categ.len]]))){ # here length(categ.color) is equal to the different number of categ
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+data1 <- data.frame(data1, categ.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)  # no need stringsAsFactors here for stat.nolog as factors remain factors
+data1$categ.color <- factor(data1$categ.color, labels = categ.color) # replace the characters of data1[, categ[categ.len]] put in the categ.color column by the categ.color (can be write like this because categ.color is length of levels of data1[, categ[categ.len]])
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", categ[categ.len], " OF categ ARGUMENT, THE FOLLOWING COLORS:\n", paste(categ.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else if(length(categ.color) == length(data1[, categ[categ.len]])){# here length(categ.color) is equal to nrow(data1) -> Modif to have length(categ.color) equal to the different number of categ (length(categ.color) == length(levels(data1[, categ[categ.len]])))
+data1 <- data.frame(data1, categ.color = categ.color, stringsAsFactors = TRUE)
+tempo.check <- unique(data1[ , c(categ[categ.len], "categ.color")])
+if( ! (nrow(tempo.check) == length(unique(categ.color)) & nrow(tempo.check) == length(unique(data1[ , categ[categ.len]])))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT HAS THE LENGTH OF data1 ROW NUMBER\nBUT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF categ ", categ[categ.len], ":\n", paste(unique(mapply(FUN = "paste", data1[ ,categ[categ.len]], data1[ ,"categ.color"])), collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+categ.color <- unique(data1$categ.color[order(data1[, categ[categ.len]])]) # Modif to have length(categ.color) equal to the different number of categ (length(categ.color) == length(levels(data1[, categ[categ.len]])))
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT HAS THE LENGTH OF data1 ROW NUMBER\nCOLORS HAVE BEEN RESPECTIVELY ASSOCIATED TO EACH CLASS OF categ ", categ[categ.len], " AS:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\n", paste(categ.color, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+}else if(length(categ.color) == 1L){
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+data1 <- data.frame(data1, categ.color = categ.color, stringsAsFactors = TRUE)
+categ.color <- rep(categ.color, length(levels(data1[, categ[categ.len]])))
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT HAS LENGTH 1, MEANING THAT ALL THE DIFFERENT CLASSES OF ", categ[categ.len], "\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(categ.color, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE (1) LENGTH 1, OR (2) THE LENGTH OF data1 NROWS AFTER NA/Inf REMOVAL, OR (3) THE LENGTH OF THE CLASSES IN THE categ ", categ[categ.len], " COLUMN. HERE IT IS COLOR LENGTH ", length(categ.color), " VERSUS CATEG LENGTH ", length(data1[, categ[categ.len]]), " AND CATEG CLASS LENGTH ", length(unique(data1[, categ[categ.len]])), "\nPRESENCE OF NA/Inf COULD BE THE PROBLEM")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+categ.color <- fun_gg_palette(length(levels(data1[, categ[categ.len]])))
+data1 <- data.frame(data1, categ.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)
+data1$categ.color <- factor(data1$categ.color, labels = categ.color)  # replace the characters of data1[, categ[categ.len]] put in the categ.color column by the categ.color (can be write like this because categ.color is length of levels of data1[, categ[categ.len]])
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL categ.color ARGUMENT -> COLORS RESPECTIVELY ATTRIBUTED TO EACH CLASS OF ", categ[categ.len], " IN data1:\n", paste(categ.color, collapse = " "), "\n", paste(levels(data1[, categ[categ.len]]), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# categ.color not NULL anymore
+categ.color <- as.character(categ.color)
+# categ.color is a character string representing the diff classes
+data1$categ.color <- factor(data1$categ.color, levels = unique(categ.color)) # ok because if categ.color is a character string, the order make class 1, class 2, etc. unique() because no duplicates allowed
+# data1$categ.color is a factor with order of levels -> categ.color
+# end management of categ.color
+# management of dot.color
+if( ! is.null(dot.color)){
+# optional legend of dot colors
+if( ! is.null(dot.categ)){
+ini.dot.categ <- dot.categ
+if( ! dot.categ %in% names(data1)){ # no need to use all() because length(dot.categ) = 1
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT MUST BE A COLUMN NAME OF data1. HERE IT IS:\n", dot.categ)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(dot.categ %in% categ){ # no need to use all() because length(dot.categ) = 1. Do not use dot.categ %in% categ[length(categ)] -> error
+# management of dot legend if dot.categ %in% categ (because legends with the same name are joined in ggplot2) 
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE COLUMN NAME OF data1 INDICATED IN THE dot.categ ARGUMENT (", dot.categ, ") HAS BEEN REPLACED BY ", paste0(dot.categ, "_DOT"), " TO AVOID MERGED LEGEND BY GGPLOT2")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+data1 <- data.frame(data1, dot.categ = data1[, dot.categ], stringsAsFactors = TRUE) # dot.categ is not a column name of data1 (checked above with reserved words)
+dot.categ <- paste0(dot.categ, "_DOT")
+names(data1)[names(data1) == "dot.categ"] <- dot.categ # paste0(dot.categ, "_DOT") is not a column name of data1 (checked above with reserved words)
+# tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT CANNOT BE A COLUMN NAME OF data1 ALREADY SPECIFIED IN THE categ ARGUMENT:\n", dot.categ, "\nINDEED, dot.categ ARGUMENT IS MADE TO HAVE MULTIPLE DOT COLORS NOT RELATED TO THE BOXPLOT CATEGORIES")
+# stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+tempo1 <- fun_check(data = data1[, dot.categ], data.name = paste0(dot.categ, " COLUMN OF data1"), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = data1[, dot.categ], data.name = paste0(dot.categ, " COLUMN OF data1"), class = "factor", na.contain = TRUE, fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ COLUMN MUST BE A FACTOR OR CHARACTER VECTOR") #
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+data1[, dot.categ] <- factor(data1[, dot.categ]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+# dot.categ column of data1 is factor from here
+if( ! is.null(dot.categ.class.order)){
+if(any(duplicated(dot.categ.class.order), na.rm = TRUE)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(dot.categ.class.order, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! (all(dot.categ.class.order %in% levels(data1[, dot.categ])) & all(levels(data1[, dot.categ]) %in% dot.categ.class.order, na.rm = TRUE))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ.class.order ARGUMENT MUST BE CLASSES OF dot.categ ARGUMENT\nHERE IT IS:\n", paste(dot.categ.class.order, collapse = " "), "\nFOR dot.categ.class.order AND IT IS:\n", paste(levels(data1[, dot.categ]), collapse = " "), "\nFOR dot.categ COLUMN (", ini.dot.categ, ") OF data1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
+}
+}else{
+if(all(dot.color == "same") & length(dot.color)== 1L){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
+dot.categ.class.order <- unlist(categ.class.order[length(categ)])
+data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order SETTING IS NULL AND dot.color IS \"same\". ORDER OF categ.class.order WILL BE APPLIED FOR LEGEND DISPLAY: ", paste(dot.categ.class.order, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+dot.categ.class.order <- sort(levels(data1[, dot.categ]))
+data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR LEGEND DISPLAY: ", paste(dot.categ.class.order, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# dot.categ.class.order not NULL anymore (character string) if dot.categ is not NULL
+if(all(dot.color == "same") & length(dot.color)== 1L){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
+if( ! identical(ini.dot.categ, categ[length(categ)])){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN dot.color ARGUMENT IS \"same\", THE COLUMN NAME IN dot.categ ARGUMENT MUST BE IDENTICAL TO THE LAST COLUMN NAME IN categ ARGUMENT. HERE IT IS:\ndot.categ: ", paste(ini.dot.categ, collapse = " "), "\ncateg: ", paste(categ, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if( ! fun_comp_1d(unlist(categ.class.order[length(categ)]), dot.categ.class.order)$identical.content){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN dot.color ARGUMENT IS \"same\",\nLAST COMPARTMENT OF categ.class.order ARGUMENT AND dot.categ.class.order ARGUMENT CANNOT BE DIFFERENT:\nLAST COMPARTMENT OF categ.class.order: ", paste(unlist(categ.class.order[length(categ)]), collapse = " "), "\ndot.categ.class.order: ", paste(dot.categ.class.order, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+for(i3 in 1:length(categ)){
+if(identical(categ[i3], ini.dot.categ) & ! identical(unlist(categ.class.order[i3]), dot.categ.class.order) & identical(sort(unlist(categ.class.order[i3])), sort(dot.categ.class.order))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE dot.categ ARGUMENT SETTING IS PRESENT IN THE categ ARGUMENT SETTING, BUT ORDER OF THE CLASSES IS NOT THE SAME:\ncateg.class.order: ", paste(unlist(categ.class.order[i3]), collapse = " "), "\ndot.categ.class.order: ", paste(dot.categ.class.order, collapse = " "), "\nNOTE THAT ORDER OF categ.class.order IS THE ONE USED FOR THE AXIS REPRESENTATION")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(is.null(dot.legend.name)){
+dot.legend.name <- if(ini.dot.categ %in% categ[length(categ)]){dot.categ}else{ini.dot.categ} #
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE dot.legend.name SETTING IS NULL -> ", dot.legend.name, " WILL BE USED AS LEGEND TITLE OF DOTS")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# dot.legend.name not NULL anymore (character string)
+}else{
+if( ! is.null(dot.categ.class.order)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order ARGUMENT IS NOT NULL, BUT IS THE dot.categ ARGUMENT\n-> dot.categ.class.order NOT CONSIDERED AS NO LEGEND WILL BE DRAWN")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# But dot.categ.class.order will be converted to NULL below (not now)
+}
+# end optional legend of dot colors
+# check the nature of color
+# integer colors into gg_palette
+tempo.check.color <- fun_check(data = dot.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem
+if(tempo.check.color == FALSE){
+# convert integers into colors
+dot.color <- fun_gg_palette(max(dot.color, na.rm = TRUE))[dot.color]
+}
+# end integer colors into gg_palette
+if(all(dot.color == "same") & length(dot.color)== 1L){# all() without na.rm -> ok because dot.color cannot be NA (tested above)
+dot.color <- categ.color # same color of the dots as the corresponding box color
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT HAS BEEN SET TO \"same\"\nTHUS, DOTS WILL HAVE THE SAME COLORS AS THE CORRESPONDING BOXPLOT")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else if( ! (all(dot.color %in% colors() | grepl(pattern = "^#", dot.color)))){ # check that all strings of low.color start by #, # all() without na.rm -> ok because dot.color cannot be NA (tested above)
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR VECTOR STARTING BY #, OR (2) COLOR NAMES GIVEN BY colors(), OR (3) INTEGERS, OR THE STRING \"same\"\nHERE IT IS: ", paste(unique(dot.color), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(any(is.na(dot.color))){ # normally no NA with is.finite
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT CONTAINS NA")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end check the nature of color
+# check the length of color
+if( ! is.null(dot.categ)){
+# optional legend of dot colors
+if(length(data1[, dot.categ]) == length(levels(data1[, dot.categ])) & length(dot.color) == length(data1[, dot.categ])){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE NUMBER OF CLASSES OF THE COLUMN ", dot.categ, " THE NUMBER OF ROWS OF THIS COLUMN AND THE NUMBER OF COLORS OF THE dot.color ARGUMENT ARE ALL EQUAL. DOT COLORS WILL BE ATTRIBUTED ACCORDING THE LEVELS OF ", dot.categ, ", NOT ACCORDING TO THE ROWS OF ", dot.categ)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if(length(dot.color) > 1 & ! (length(dot.color) == length(unique(data1[, dot.categ])) | length(dot.color) == length(data1[, dot.categ]))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN LENGTH OF THE dot.color ARGUMENT IS MORE THAN 1, IT MUST BE EQUAL TO THE NUMBER OF 1) ROWS OR 2) LEVELS OF dot.categ COLUMN (", dot.categ, "):\ndot.color: ", paste(dot.color, collapse = " "), "\ndot.categ LEVELS: ", paste(levels(data1[, dot.categ]), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else if(length(dot.color) > 1 & length(dot.color) == length(unique(data1[, dot.categ]))){
+data1 <- data.frame(data1, dot.color = data1[, dot.categ], stringsAsFactors = TRUE)
+data1$dot.color <- factor(data1$dot.color, labels = dot.color) # do not use labels = unique(dot.color). Otherwise, we can have green1 green2 when dot.color is c("green", "green")
+}else if(length(dot.color) > 1 & length(dot.color) == length(data1[, dot.categ])){
+data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
+}else if(length(dot.color)== 1L){ # to deal with single color. Warning: & length(dot.categ.class.order) > 1 removed because otherwise, the data1 is not with dot.color column when length(dot.categ.class.order) == 1
+data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
+}
+dot.color <- as.character(unique(data1$dot.color[order(data1[, dot.categ])])) # reorder the dot.color character vector
+if(length(dot.color)== 1L & length(dot.categ.class.order) > 1){ # to deal with single color
+dot.color <- rep(dot.color, length(dot.categ.class.order))
+}
+tempo.check <- unique(data1[ , c(dot.categ, "dot.color")])
+if(length(unique(data1[ , "dot.color"])) > 1 & ( ! (nrow(tempo.check) == length(unique(data1[ , "dot.color"])) & nrow(tempo.check) == length(unique(data1[ , dot.categ]))))){ # length(unique(data1[ , "dot.color"])) > 1 because if only one color, can be attributed to each class of dot.categ
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF dot.categ (", dot.categ, ") COLUMN:\n", paste(unique(mapply(FUN = "paste", data1[ , dot.categ], data1[ ,"dot.color"])), collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN dot.categ ARGUMENT (", ini.dot.categ, "), THE FOLLOWING COLORS OF DOTS:\n", paste(dot.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(data1[, dot.categ]), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# dot.color is a character string representing the diff classes of dot.categ
+# data1$dot.color is a factor with order of levels -> dot.categ
+# end optional legend of dot colors
+}else{
+categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
+if(length(dot.color) == length(levels(data1[, categ[categ.len]]))){ # here length(dot.color) is equal to the different number of categ
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+data1 <- data.frame(data1, dot.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)
+data1$dot.color <- factor(data1$dot.color, labels = dot.color)
+if(box.alpha != 0){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", categ[categ.len], " OF categ ARGUMENT, THE FOLLOWING COLORS:\n", paste(dot.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else if(length(dot.color) == length(data1[, categ[categ.len]])){# here length(dot.color) is equal to nrow(data1) -> Modif to have length(dot.color) equal to the different number of categ (length(dot.color) == length(levels(data1[, categ[categ.len]])))
+data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
+}else if(length(dot.color)== 1L & ! all(dot.color == "same")){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
+# data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
+data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
+dot.color <- rep(dot.color, length(levels(data1[, categ[categ.len]])))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT HAS LENGTH 1, MEANING THAT ALL THE DIFFERENT CLASSES OF ", categ[categ.len], "\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(dot.color, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE (1) LENGTH 1, OR (2) THE LENGTH OF data1 NROWS AFTER NA/Inf REMOVAL, OR (3) THE LENGTH OF THE CLASSES IN THE categ ", categ[categ.len], " COLUMN. HERE IT IS COLOR LENGTH ", length(dot.color), " VERSUS CATEG LENGTH ", length(data1[, categ[categ.len]]), " AND CATEG CLASS LENGTH ", length(unique(data1[, categ[categ.len]])), "\nPRESENCE OF NA/Inf COULD BE THE PROBLEM")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end check the length of color
+dot.color <- as.character(dot.color)
+# dot.color is a character string representing the diff classes
+data1$dot.color <- factor(data1$dot.color, levels = unique(dot.color)) # ok because if dot.color is a character string, the order make class 1, class 2, etc. If dot.color is a column of data1, then levels will be created, without incidence, except if dot.categ specified (see below). unique() because no duplicates allowed
+# data1$dot.color is a factor with order of levels -> dot.color
+}
+# end optional legend of dot colors
+}else if(is.null(dot.color) & ! (is.null(dot.categ) & is.null(dot.categ.class.order) & is.null(dot.legend.name))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") dot.categ OR dot.categ.class.order OR dot.legend.name ARGUMENT HAS BEEN SPECIFIED BUT dot.color ARGUMENT IS NULL (NO DOT PLOTTED)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# dot.color either NULL (no dot plotted) or character string (potentially representing the diff classes of dot.categ)
+# data1$dot.color is either NA or a factor (with order of levels -> depending on dot.categ or categ[length(categ)], or other
+if(is.null(dot.categ)){
+dot.categ.class.order <- NULL # because not used anyway
+}
+# dot.categ.class.order either NULL if dot.categ is NULL (no legend displayed) or character string (potentially representing the diff classes of dot.categ)
+# end management of dot.color
+if(is.null(dot.color) & box.fill == FALSE & dot.alpha <= 0.025){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE FOLLOWING ARGUMENTS WERE SET AS:\ndot.color = NULL (NOT ALL DOTS BUT ONLY POTENTIAL OUTLIER DOTS DISPLAYED)\nbox.fill = FALSE (NO FILLING COLOR FOR BOTH BOXES AND POTENTIAL OUTLIER DOTS)\ndot.alpha = ", fun_round(dot.alpha, 4), "\n-> POTENTIAL OUTLIER DOTS MIGHT NOT BE VISIBLE BECAUSE ALMOST TRANSPARENT")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if(is.null(dot.color) & box.fill == FALSE & dot.border.size == 0){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE FOLLOWING ARGUMENTS WERE SET AS:\ndot.color = NULL (NOT ALL DOTS BUT ONLY POTENTIAL OUTLIER DOTS DISPLAYED)\nbox.fill = FALSE (NO FILLING COLOR FOR BOTH BOXES AND POTENTIAL OUTLIER DOTS)\ndot.border.size = 0 (NO BORDER FOR POTENTIAL OUTLIER DOTS)\n-> THESE SETTINGS ARE NOT ALLOWED BECAUSE THE POTENTIAL OUTLIER DOTS WILL NOT BE VISIBLE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# integer dot.border.color into gg_palette
+if( ! is.null(dot.border.color)){
+tempo <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
+if(tempo$problem == FALSE){ # convert integers into colors
+dot.border.color <- fun_gg_palette(max(dot.border.color, na.rm = TRUE))[dot.border.color]
+}
+}
+# end integer dot.border.color into gg_palette
+# na detection and removal (done now to be sure of the correct length of categ)
+column.check <- c("categ.color", if( ! is.null(dot.color)){"dot.color"}) # 
+if(any(is.na(data1[, column.check]))){ # data1 used here instead of data1.ini in case of new NaN created by log conversion (neg values) # normally no NA with is.na
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS ", paste(column.check, collapse = " "), " OF data1 AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+for(i2 in 1:length(column.check)){
+if(any(is.na(data1[, column.check[i2]]))){ # normally no NA with is.na
+tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i2], " OF data1")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n", tempo.warn)))
+}
+}
+tempo <- unique(unlist(lapply(lapply(c(data1[column.check]), FUN = is.na), FUN = which)))
+removed.row.nb <- c(removed.row.nb, tempo)
+removed.rows <- rbind(removed.rows, data1[tempo, ], stringsAsFactors = FALSE) # here data1 used because categorical columns tested
+if(length(tempo) != 0){
+data1 <- data1[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
+data1.ini <- data1.ini[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
+for(i3 in 1:length(column.check)){
+if(any( ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]]), na.rm = TRUE)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i3], " OF data1, THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA/Inf REMOVAL (IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[, column.check[i3]])[ ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]])], collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+}
+for(i2 in 1:length(column.check)){
+if(column.check[i2] == "categ.color"){
+categ.color <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
+if(length(categ.color)== 1L & length(unlist(categ.class.order[length(categ)])) > 1){ # to deal with single color
+categ.color <- rep(categ.color, length(unlist(categ.class.order[length(categ)])))
+}
+data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(categ.color))
+}
+if(column.check[i2] == "dot.color"){
+dot.color <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
+if(length(dot.color)== 1L & length(dot.categ.class.order) > 1){ # to deal with single color. If dot.categ.class.order == NULL (which is systematically the case if dot.categ == NULL), no rep(dot.color, length(dot.categ.class.order)
+dot.color <- rep(dot.color, length(dot.categ.class.order))
+}
+data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(dot.color))
+}
+}
+}
+# end na detection and removal (done now to be sure of the correct length of categ)
+# From here, data1 and data.ini have no more NA or NaN
+# end other checkings
+# reserved word checking
+#already done above
+# end reserved word checking
+# end second round of checking and data preparation
+
+
+# package checking
+fun_pack(req.package = c(
+"ggplot2", 
+"gridExtra", 
+"lemon", 
+"scales"
+), lib.path = lib.path)
+# end package checking
+
+
+
+
+
+# main code
+# y coordinates recovery (create ini.box.coord, dot.coord and modify data1)
+if(length(categ)== 1L){
+# width commputations
+box.width2 <- box.width
+box.space <- 0 # to inactivate the shrink that add space between grouped boxes, because no grouped boxes here
+# end width commputations
+# data1 check categ order for dots coordinates recovery
+data1 <- data.frame(data1, categ.check = data1[, categ[1]], stringsAsFactors = TRUE)
+data1$categ.check <- as.integer(data1$categ.check) # to check that data1[, categ[1]] and dot.coord$group are similar, during merging
+# end data1 check categ order for dots coordinates recovery
+# per box dots coordinates recovery
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[1]), stroke = dot.border.size, size = dot.size, alpha = dot.alpha, shape = 21))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(is.null(categ.color)){rep(NA, length(unique(data1[, categ[1]])))}else if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[1]])))}else{categ.color})) # categ.color used for dot colors because at that stage, we do not care about colors
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[1]), coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf})) # fill because this is what is used with geom_box # to easily have the equivalent of the grouped boxes
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[1]])))}else{categ.color}))
+# end per box dots coordinates recovery
+}else if(length(categ) == 2L){
+# width commputations
+box.width2 <- box.width / length(unique(data1[, categ[length(categ)]])) # real width of each box in x-axis unit, among the set of grouped box. Not relevant if no grouped boxes length(categ)== 1L
+# end width commputations
+# data1 check categ order for dots coordinates recovery
+tempo.factor <- paste0(data1[order(data1[, categ[2]], data1[, categ[1]]), categ[2]], "_", data1[order(data1[, categ[2]], data1[, categ[1]]), categ[1]])
+data1 <- data.frame(data1[order(data1[, categ[2]], data1[, categ[1]]), ], categ.check = factor(tempo.factor, levels = unique(tempo.factor)), stringsAsFactors = TRUE)
+data1$categ.check <- as.integer(data1$categ.check)
+# end data1 check categ order for dots coordinates recovery
+# per box dots coordinates recovery
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[2]), stroke = dot.border.size, size = dot.size, alpha = dot.alpha, shape = 21))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(is.null(categ.color)){rep(NA, length(unique(data1[, categ[2]])))}else if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[2]])))}else{categ.color})) # categ.color used for dot colors because at that stage, we do not care about colors
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[2]), coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf})) # fill because this is what is used with geom_box # to easily have the equivalent of the grouped boxes
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[2]])))}else{categ.color}))
+# end per box dots coordinates recovery
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if( ! is.null(stat.pos)){
+stat.just <- fun_gg_just(
+angle = stat.angle, 
+pos = ifelse(
+vertical == TRUE, 
+ifelse(stat.pos == "top", "bottom", "top"), # "bottom" because we want justification for text that are below the ref point which is the top of the graph. The opposite for "above"
+ifelse(stat.pos == "top", "left", "right") # "left" because we want justification for text that are on the left of the ref point which is the right border of the graph. The opposite for "above"
+), 
+kind = "text"
+)
+}
+# has in fact no interest because ggplot2 does not create room for geom_text()
+tempo.data.max <- data1[which.max(data1[, y]), ]
+tempo.data.max <- data.frame(tempo.data.max, label = formatC(tempo.data.max[, y], digit = 2, drop0trailing = TRUE, format = "f"), stringsAsFactors = TRUE)
+# end has in fact no interest because ggplot2 does not create room for geom_text()
+tempo.graph.info.ini <- ggplot2::ggplot_build(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if( ! is.null(stat.pos)){' + ggplot2::geom_text(data = tempo.data.max, mapping = ggplot2::aes_string(x = 1, y = y, label = "label"), size = stat.size, color = "black", angle = stat.angle, hjust = stat.just$hjust, vjust = stat.just$vjust)'})))) # added here to have room for annotation
+dot.coord <- tempo.graph.info.ini$data[[1]]
+dot.coord$x <- as.numeric(dot.coord$x) # because weird class
+dot.coord$PANEL <- as.numeric(dot.coord$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
+tempo.mean <- aggregate(x = dot.coord$y, by = list(dot.coord$group, dot.coord$PANEL), FUN = mean, na.rm = TRUE)
+names(tempo.mean)[names(tempo.mean) == "x"] <- "MEAN"
+names(tempo.mean)[names(tempo.mean) == "Group.1"] <- "BOX"
+names(tempo.mean)[names(tempo.mean) == "Group.2"] <- "PANEL"
+dot.coord <- data.frame(
+dot.coord[order(dot.coord$group, dot.coord$y), ], # dot.coord$PANEL deals below
+y.check = as.double(data1[order(data1$categ.check, data1[, y]), y]), 
+categ.check = data1[order(data1$categ.check, data1[, y]), "categ.check"], 
+dot.color = if(is.null(dot.color)){NA}else{data1[order(data1$categ.check, data1[, y]), "dot.color"]}, 
+data1[order(data1$categ.check, data1[, y]), ][categ], # avoid the renaming below
+stringsAsFactors = TRUE
+) # y.check to be sure that the order is the same between the y of data1 and the y of dot.coord
+# names(dot.coord)[names(dot.coord) == "tempo.categ1"] <- categ[1]
+if( ! is.null(dot.categ)){
+dot.coord <- data.frame(dot.coord, data1[order(data1$categ.check, data1[, y]), ][dot.categ], stringsAsFactors = TRUE) # avoid the renaming
+}
+if( ! is.null(facet.categ)){
+dot.coord <- data.frame(dot.coord, data1[order(data1$categ.check, data1[, y]), ][facet.categ], stringsAsFactors = TRUE) # for facet panels
+tempo.test <- NULL
+for(i2 in 1:length(facet.categ)){
+tempo.test <- paste0(tempo.test, ".", formatC(as.numeric(dot.coord[, facet.categ[i2]]), width = nchar(max(as.numeric(dot.coord[, facet.categ[i2]]), na.rm = TRUE)), flag = "0")) # convert factor into numeric with leading zero for proper ranking # merge the formatC() to create a new factor. The convertion to integer should recreate the correct group number. Here as.numeric is used and not as.integer in case of numeric in facet.categ (because comes from add and not checked by fun_check, contrary to categ)
+}
+tempo.test <- as.integer(factor(tempo.test))
+if( ! identical(as.integer(dot.coord$PANEL), tempo.test)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nas.integer(dot.coord$PANEL) AND tempo.test MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(dot.tidy == TRUE){
+if( ! is.null(dot.categ)){
+dot.coord <- data.frame(dot.coord, tidy_group = data1[order(data1$categ.check, data1[, y]), ][, dot.categ], stringsAsFactors = TRUE) # avoid the renaming
+# tidy_group_coord is to be able to fuse table when creating the table for dot coordinates
+if(dot.categ %in% categ){
+dot.coord <- data.frame(dot.coord, tidy_group_coord = dot.coord$group, stringsAsFactors = TRUE)
+}else{
+dot.coord <- data.frame(dot.coord, tidy_group_coord = as.integer(factor(paste0(
+formatC(as.integer(dot.coord[, categ[1]]), width = nchar(max(as.integer(dot.coord[, categ[1]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
+".", 
+if(length(categ) == 2L){formatC(as.integer(dot.coord[, categ[2]]), width = nchar(max(as.integer(dot.coord[, categ[2]]), na.rm = TRUE)), flag = "0")}, # convert factor into numeric with leading zero for proper ranking
+if(length(categ) == 2L){"."}, 
+formatC(as.integer(dot.coord[, dot.categ]), width = nchar(max(as.integer(dot.coord[, dot.categ]), na.rm = TRUE)), flag = "0") # convert factor into numeric with leading zero for proper ranking
+)), stringsAsFactors = TRUE) # merge the 2 or 3 formatC() to create a new factor. The convertion to integer should recreate the correct group number
+) # for tidy dot plots
+}
+}else{
+dot.coord <- data.frame(dot.coord, tidy_group = if(length(categ)== 1L){
+dot.coord[, categ]}else{as.integer(factor(paste0(
+formatC(as.integer(dot.coord[, categ[1]]), width = nchar(max(as.integer(dot.coord[, categ[1]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
+".", 
+formatC(as.integer(dot.coord[, categ[2]]), width = nchar(max(as.integer(dot.coord[, categ[2]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
+)), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
+}) # for tidy dot plots
+# tidy_group_coord is to be able to fuse table when creating the table for dot coordinates
+dot.coord <- data.frame(dot.coord, tidy_group_coord = dot.coord$group, stringsAsFactors = TRUE)
+}
+}
+if( ! (identical(dot.coord$y, dot.coord$y.check) & identical(dot.coord$group, dot.coord$categ.check))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\n(dot.coord$y AND dot.coord$y.check) AS WELL AS (dot.coord$group AND dot.coord$categ.check) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+if( ! identical(tempo.mean[order(tempo.mean$BOX, tempo.mean$PANEL), ]$BOX, unique(dot.coord[order(dot.coord$group, dot.coord$PANEL), c("group", "PANEL")])$group)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\n(tempo.mean$BOX, tempo.mean$PANEL) AND (dot.coord$group, dot.coord$PANEL) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+tempo <- unique(dot.coord[order(dot.coord$group, dot.coord$PANEL), c(categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){if(dot.categ != ini.dot.categ){dot.categ}}, if( ! is.null(facet.categ)){facet.categ}), drop = FALSE])
+# names(tempo) <- paste0(names(tempo), ".mean")
+tempo.mean <- data.frame(tempo.mean[order(tempo.mean$BOX, tempo.mean$PANEL), ], tempo, stringsAsFactors = TRUE)
+}
+}
+# at that stage, categ color and dot color are correctly attributed in data1, box.coord and dot.coord
+# end y dot coordinates recovery (create ini.box.coord, dot.coord and modify data1)
+# ylim range
+if(is.null(y.lim)){
+y.lim <- tempo.graph.info.ini$layout$panel_params[[1]]$y.range # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+if(any(( ! is.finite(y.lim)) | is.na(y.lim)) | length(y.lim) != 2){ # kept but normally no more Inf in data1 # normally no NA with is.finite, etc.
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\ntempo.graph.info.ini$layout$panel_params[[1]]$y.range[1] CONTAINS NA OR Inf OR HAS LENGTH 1")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else if(y.log != "no"){
+y.lim <- get(y.log)(y.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+if(y.log != "no"){
+# normally this control is not necessary anymore
+if(any( ! is.finite(y.lim))){ # normally no NA with is.finite
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+if(suppressWarnings(all(y.lim %in% c(Inf, -Inf)))){ # all() without na.rm -> ok because y.lim cannot be NA (tested above)
+# normally this control is not necessary anymore
+tempo.cat <- paste0("ERROR IN ", function.name, " y.lim CONTAINS Inf VALUES, MAYBE BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY OR BECAUSE OF LOG SCALE REQUIREMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+if(suppressWarnings(any(is.na(y.lim)))){ # normally no NA with is.na
+# normally this control is not necessary anymore
+tempo.cat <- paste0("ERROR IN ", function.name, " y.lim CONTAINS NA OR NaN VALUES, MAYBE BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY OR BECAUSE OF LOG SCALE REQUIREMENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+y.lim.order <- order(y.lim) # to deal with inverse axis
+y.lim <- sort(y.lim)
+y.lim[1] <- y.lim[1] - abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.bottom.extra.margin, y.top.extra.margin) # diff(y.lim.order) > 0 medians not inversed axis
+y.lim[2] <- y.lim[2] + abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.top.extra.margin, y.bottom.extra.margin) # diff(y.lim.order) > 0 medians not inversed axis
+if(y.include.zero == TRUE){ # no need to check y.log != "no" because done before
+y.lim <- range(c(y.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+}
+y.lim <- y.lim[y.lim.order]
+if(any(is.na(y.lim))){ # normally no NA with is.na
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 2")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end ylim range
+
+
+
+
+
+
+# drawing
+# constant part
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add is directly put here to deal with additional variable of data, like when using facet_grid. No problem if add is a theme, will be dealt below
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::xlab(if(is.null(x.lab)){categ[1]}else{x.lab}))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ylab(if(is.null(y.lab)){y}else{y.lab}))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
+# text angle management
+axis.just <- fun_gg_just(angle = x.angle, pos = ifelse(vertical == TRUE, "bottom", "left"), kind = "axis")
+# end text angle management
+add.check <- TRUE
+if( ! is.null(add)){ # if add is NULL, then = 0
+if(grepl(pattern = "ggplot2\\s*::\\s*theme", add) == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT\n-> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER\n-> article ARGUMENT WILL BE IGNORED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+add.check <- FALSE
+}
+}
+if(add.check == TRUE & article == TRUE){
+# WARNING: not possible to add theme()several times. NO message but the last one overwrites the others
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
+if(grid == TRUE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_line(size = 0.5), 
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+axis.line.y.left = ggplot2::element_line(colour = "black"), # draw lines for the y axis
+axis.line.x.bottom = ggplot2::element_line(colour = "black"), # draw lines for the x axis
+panel.grid.major.x = if(vertical == TRUE){NULL}else{ggplot2::element_line(colour = "grey85", size = 0.75)},
+panel.grid.major.y = if(vertical == TRUE){ggplot2::element_line(colour = "grey85", size = 0.75)}else{NULL},
+panel.grid.minor.y = if(vertical == TRUE){ggplot2::element_line(colour = "grey90", size = 0.25)}else{NULL},
+axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
+axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)},
+strip.background = ggplot2::element_rect(fill = NA, colour = NA) # for facet background
+))
+}else{
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_line(size = 0.5), 
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+axis.line.y.left = ggplot2::element_line(colour = "black"), 
+axis.line.x.bottom = ggplot2::element_line(colour = "black"),
+axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
+axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)},
+strip.background = ggplot2::element_rect(fill = NA, colour = NA)
+))
+}
+}else if(add.check == TRUE & article == FALSE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_line(size = 0.5), 
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+panel.background = ggplot2::element_rect(fill = "grey95"), 
+axis.line.y.left = ggplot2::element_line(colour = "black"), 
+axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
+panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.minor.x = ggplot2::element_blank(), 
+panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
+strip.background = ggplot2::element_rect(fill = NA, colour = NA),
+axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
+axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}
+))
+}
+# Contrary to fun_gg_bar(), cannot plot the boxplot right now, because I need the dots plotted first
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, group = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), color = NA, width = box.width, fill = NA)) # this is to set the graph (i.e., a blanck boxplot to be able to use x coordinates to plot dots before boxes)
+# end constant part
+
+
+
+
+# graphic info recovery (including means)
+tempo.graph.info <- ggplot2::ggplot_build(eval(parse(text = paste0(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, notch = box.notch, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}) + ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color})')))) # will be recovered later again, when ylim will be considered
+tempo.yx.ratio <- (tempo.graph.info$layout$panel_params[[1]]$y.range[2] - tempo.graph.info$layout$panel_params[[1]]$y.range[1]) / (tempo.graph.info$layout$panel_params[[1]]$x.range[2] - tempo.graph.info$layout$panel_params[[1]]$x.range[1])
+box.coord <- tempo.graph.info$data[[2]] # to have the summary statistics of the plot. Contrary to ini.box.plot, now integrates ylim Here because can be required for stat.pos when just box are plotted
+box.coord$x <- as.numeric(box.coord$x) # because x is of special class that block comparison of values using identical
+box.coord$PANEL <- as.numeric(box.coord$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
+box.coord <- box.coord[order(box.coord$group, box.coord$PANEL), ]
+if( ! (identical(tempo.mean$BOX, box.coord$group) & identical(tempo.mean$PANEL, box.coord$PANEL))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nidentical(tempo.mean$BOX, box.coord$group) & identical(tempo.mean$PANEL, box.coord$PANEL) DO NOT HAVE THE SAME VALUE ORDER")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+# tempo <- c(categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){if(dot.categ != ini.dot.categ){dot.categ}}, if( ! is.null(facet.categ)){facet.categ})
+if(any(names(tempo.mean) %in% names(box.coord), na.rm = TRUE)){
+names(tempo.mean)[names(tempo.mean) %in% names(box.coord)] <- paste0(names(tempo.mean)[names(tempo.mean) %in% names(box.coord)], ".mean")
+}
+box.coord <- data.frame(box.coord, tempo.mean, stringsAsFactors = TRUE)
+}
+# end graphic info recovery (including means)
+
+
+
+# stat output (will also serve for boxplot and mean display)
+# x not added know to do not have them in stat.nolog
+stat <- data.frame(
+MIN = box.coord$ymin_final, 
+QUART1 = box.coord$lower, 
+MEDIAN = box.coord$middle, 
+MEAN = box.coord$MEAN, 
+QUART3 = box.coord$upper, 
+MAX = box.coord$ymax_final, 
+WHISK_INF = box.coord$ymin, 
+BOX_INF = box.coord$lower, 
+NOTCH_INF = box.coord$notchlower, 
+NOTCH_SUP = box.coord$notchupper, 
+BOX_SUP = box.coord$upper, 
+WHISK_SUP = box.coord$ymax, 
+OUTLIERS = box.coord["outliers"], 
+tempo.mean[colnames(tempo.mean) != "MEAN"], 
+COLOR = box.coord$fill, 
+stringsAsFactors = TRUE
+) # box.coord["outliers"] written like this because it is a list. X coordinates not put now because several features to set
+names(stat)[names(stat) == "outliers"] <- "OUTLIERS"
+stat.nolog <- stat # stat.nolog ini will serve for outputs
+if(y.log != "no"){
+stat.nolog[c("MIN", "QUART1", "MEDIAN", "MEAN", "QUART3", "MAX", "WHISK_INF", "BOX_INF", "NOTCH_INF", "NOTCH_SUP", "BOX_SUP", "WHISK_SUP")] <- ifelse(y.log == "log2", 2, 10)^(stat.nolog[c("MIN", "QUART1", "MEDIAN", "MEAN", "QUART3", "MAX", "WHISK_INF", "BOX_INF", "NOTCH_INF", "NOTCH_SUP", "BOX_SUP", "WHISK_SUP")])
+stat.nolog$OUTLIERS <- lapply(stat.nolog$OUTLIERS, FUN = function(X){ifelse(y.log == "log2", 2, 10)^X})
+}
+# end stat output (will also serve for boxplot and mean display)
+
+
+
+
+
+
+# x coordinates management (for random plotting and for stat display)
+# width commputations
+width.ini <- c(box.coord$xmax - box.coord$xmin)[1] # all the box widths are equal here. Only the first one taken
+width.correct <- width.ini * box.space / 2
+if( ! (identical(stat$BOX, box.coord$group) & identical(stat$PANEL, box.coord$PANEL))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nidentical(stat$BOX, box.coord$group) & identical(stat$PANEL, box.coord$PANEL) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+stat <- data.frame(
+stat, 
+X = box.coord$x, 
+X_BOX_INF = box.coord$xmin + width.correct, 
+X_BOX_SUP = box.coord$xmax - width.correct, 
+X_NOTCH_INF = box.coord$x - (box.coord$x - (box.coord$xmin + width.correct)) / 2, 
+X_NOTCH_SUP = box.coord$x + (box.coord$x - (box.coord$xmin + width.correct)) / 2, 
+X_WHISK_INF = box.coord$x - (box.coord$x - (box.coord$xmin + width.correct)) * box.whisker.width, 
+X_WHISK_SUP = box.coord$x + (box.coord$x - (box.coord$xmin + width.correct)) * box.whisker.width, 
+# tempo.mean[colnames(tempo.mean) != "MEAN"], # already added above
+stringsAsFactors = TRUE
+)
+stat$COLOR <- factor(stat$COLOR, levels = unique(categ.color))
+if( ! all(stat$NOTCH_SUP < stat$BOX_SUP & stat$NOTCH_INF > stat$BOX_INF, na.rm = TRUE) & box.notch == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") SOME NOTCHES ARE BEYOND BOX HINGES. TRY ARGUMENT box.notch = FALSE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+dot.jitter <- c((box.coord$xmax - width.correct) - (box.coord$xmin + width.correct))[1] * dot.jitter # real dot.jitter. (box.coord$xmin + width.correct) - (box.coord$xmax - width.correct))[1] is the width of the box. Is equivalent to (box.coord$x - (box.coord$xmin + width.correct))[1] * 2
+# end width commputations
+if( ! is.null(dot.color)){
+# random dots
+if(dot.tidy == FALSE){
+dot.coord.rd1 <- merge(dot.coord, box.coord[c("fill", "PANEL", "group", "x")], by = c("PANEL", "group"), sort = FALSE) # rd for random. Send the coord of the boxes into the coord data.frame of the dots (in the column x.y). WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in box.coord. Thus, no need to consider fill column
+if(nrow(dot.coord.rd1) != nrow(dot.coord)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.rd1 DATA FRAME. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+sampled.dot.jitter <- if(nrow(dot.coord.rd1)== 1L){runif(n = nrow(dot.coord.rd1), min = - dot.jitter / 2, max = dot.jitter / 2)}else{sample(x = runif(n = nrow(dot.coord.rd1), min = - dot.jitter / 2, max = dot.jitter / 2), size = nrow(dot.coord.rd1), replace = FALSE)}
+dot.coord.rd2 <- data.frame(dot.coord.rd1, dot.x = dot.coord.rd1$x.y + sampled.dot.jitter, stringsAsFactors = TRUE) # set the dot.jitter thanks to runif and dot.jitter range. Then, send the coord of the boxes into the coord data.frame of the dots (in the column x.y)
+if(length(categ)== 1L){
+tempo.data1 <- unique(data.frame(data1[categ[1]], group = as.integer(data1[, categ[1]]), stringsAsFactors = TRUE)) # categ[1] is factor
+names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
+verif <- paste0(categ[1], ".check")
+}else if(length(categ) == 2L){
+tempo.data1 <- unique(
+data.frame(
+data1[c(categ[1], categ[2])], 
+group = as.integer(factor(paste0(
+formatC(as.integer(data1[, categ[2]]), width = nchar(max(as.integer(data1[, categ[2]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
+".", 
+formatC(as.integer(data1[, categ[1]]), width = nchar(max(as.integer(data1[, categ[1]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
+)), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
+)
+) # categ[2] first if categ[2] is used to make the categories in ggplot and categ[1] is used to make the x-axis
+names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
+names(tempo.data1)[names(tempo.data1) == categ[2]] <- paste0(categ[2], ".check")
+verif <- c(paste0(categ[1], ".check"), paste0(categ[2], ".check"))
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+dot.coord.rd3 <- merge(dot.coord.rd2, tempo.data1, by = intersect("group", "group"), sort = FALSE) # send the factors of data1 into coord. WARNING: I have replaced by = "group" by intersect("group", "group") because of an error due to wrong group group merging in dot.coord.rd3
+if(nrow(dot.coord.rd3) != nrow(dot.coord) | ( ! fun_comp_2d(dot.coord.rd3[categ], dot.coord.rd3[verif])$identical.content)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.rd3 DATA FRAME. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end random dots
+}
+# tidy dots
+# coordinates are recovered during plotting (see dot.coord.tidy1 below)
+# end tidy dots
+}
+# end x coordinates management (for random plotting and for stat display)
+
+
+
+
+
+# boxplot display before dot display if box.fill = TRUE
+coord.names <- NULL
+# creation of the data frame for (main box + legend) and data frame for means
+if(box.notch == FALSE){
+for(i3 in 1:length(categ)){
+if(i3== 1L){
+tempo.polygon <- data.frame(GROUPX = c(t(stat[, rep(categ[i3], 5)])), stringsAsFactors = TRUE)
+}else{
+tempo.polygon <- cbind(tempo.polygon, c(t(stat[, rep(categ[i3], 5)])), stringsAsFactors = TRUE)
+}
+}
+names(tempo.polygon) <- categ
+tempo.polygon <- data.frame(X = c(t(stat[, c("X_BOX_INF", "X_BOX_SUP", "X_BOX_SUP", "X_BOX_INF", "X_BOX_INF")])), Y = c(t(stat[, c("BOX_INF", "BOX_INF", "BOX_SUP", "BOX_SUP", "BOX_INF")])), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), BOX = as.character(c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX")]))), tempo.polygon, stringsAsFactors = TRUE)
+if( ! is.null(facet.categ)){
+for(i4 in 1:length(facet.categ)){
+tempo.polygon <- data.frame(tempo.polygon, c(t(stat[, c(facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4])])), stringsAsFactors = TRUE)
+names(tempo.polygon)[length(names(tempo.polygon))] <- facet.categ[i4]
+}
+}
+}else{
+for(i3 in 1:length(categ)){
+if(i3== 1L){
+tempo.polygon <- data.frame(GROUPX = c(t(stat[, rep(categ[i3], 11)])), stringsAsFactors = TRUE)
+}else{
+tempo.polygon <- cbind(tempo.polygon, c(t(stat[, rep(categ[i3], 11)])), stringsAsFactors = TRUE)
+}
+}
+names(tempo.polygon) <- categ
+tempo.polygon <- data.frame(X = c(t(stat[, c("X_BOX_INF", "X_BOX_SUP", "X_BOX_SUP", "X_NOTCH_SUP", "X_BOX_SUP", "X_BOX_SUP", "X_BOX_INF", "X_BOX_INF", "X_NOTCH_INF", "X_BOX_INF", "X_BOX_INF")])), Y = c(t(stat[, c("BOX_INF", "BOX_INF", "NOTCH_INF", "MEDIAN", "NOTCH_SUP", "BOX_SUP", "BOX_SUP", "NOTCH_SUP", "MEDIAN", "NOTCH_INF", "BOX_INF")])), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), BOX = as.character(c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX")]))), tempo.polygon, stringsAsFactors = TRUE)
+if( ! is.null(facet.categ)){
+for(i4 in 1:length(facet.categ)){
+tempo.polygon <- data.frame(tempo.polygon, c(t(stat[, c(facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4])])), stringsAsFactors = TRUE)
+names(tempo.polygon)[length(names(tempo.polygon))] <- facet.categ[i4]
+}
+}
+}
+tempo.polygon$COLOR <- factor(tempo.polygon$COLOR, levels = unique(categ.color))
+if( ! is.null(categ.class.order)){
+for(i3 in 1:length(categ)){
+tempo.polygon[, categ[i3]] <- factor(tempo.polygon[, categ[i3]], levels = categ.class.order[[i3]])
+}
+}
+# modified name of dot.categ column (e.g., "Categ1_DOT") must be included for boxplot using ridy dots
+if( ! is.null(dot.color) & ! is.null(dot.categ)){
+if(dot.categ != ini.dot.categ){
+tempo.polygon <- data.frame(tempo.polygon, GROUPX = tempo.polygon[, ini.dot.categ], stringsAsFactors = TRUE)
+names(tempo.polygon)[names(tempo.polygon) == "GROUPX"] <- dot.categ
+
+}
+}
+tempo.diamon.mean <- data.frame(X = c(t(stat[, c("X", "X_NOTCH_INF", "X", "X_NOTCH_SUP", "X")])), Y = c(t(cbind(stat["MEAN"] - (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stat["MEAN"], stat["MEAN"] + (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stat["MEAN"], stat["MEAN"] - (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stringsAsFactors = TRUE))), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), GROUP = c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX")])), stringsAsFactors = TRUE) # stringsAsFactors = TRUE for cbind() because stat["MEAN"] is a data frame. Otherwise, stringsAsFactors is not an argument for cbind() on vectors
+if( ! is.null(facet.categ)){
+for(i3 in 1:length(facet.categ)){
+tempo.diamon.mean <- data.frame(tempo.diamon.mean, c(t(stat[, c(facet.categ[i3], facet.categ[i3], facet.categ[i3], facet.categ[i3], facet.categ[i3])])), stringsAsFactors = TRUE)
+names(tempo.diamon.mean)[length(names(tempo.diamon.mean))] <- facet.categ[i3]
+}
+}
+tempo.diamon.mean$COLOR <- factor(tempo.diamon.mean$COLOR, levels = unique(categ.color))
+# end creation of the data frame for (main box + legend) and data frame for means
+if(box.fill == TRUE){
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[length(categ)], fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, size = box.line.size, notch = box.notch, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}, alpha = box.alpha, outlier.shape = if( ! is.null(dot.color)){NA}else{21}, outlier.color = if( ! is.null(dot.color)){NA}else{dot.border.color}, outlier.fill = if( ! is.null(dot.color)){NA}else{NULL}, outlier.size = if( ! is.null(dot.color)){NA}else{dot.size}, outlier.stroke = if( ! is.null(dot.color)){NA}else{dot.border.size}, outlier.alpha = if( ! is.null(dot.color)){NA}else{dot.alpha})) # the color, size, etc. of the outliers are dealt here. outlier.color = NA to do not plot outliers when dots are already plotted. Finally, boxplot redrawn (see below)
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_polygon(
+data = tempo.polygon, 
+mapping = ggplot2::aes_string(x = "X", y = "Y", group = "BOX", fill = categ[length(categ)], color = categ[length(categ)]), 
+size = box.line.size, 
+alpha = box.alpha # works only for fill, not for color
+))
+coord.names <- c(coord.names, "main.box")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "sup.whisker")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_INF, yend = WHISK_INF, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "inf.whisker")
+if(box.whisker.width > 0){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha, lineend = "round")) # 
+coord.names <- c(coord.names, "sup.whisker.edge")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_INF, yend = WHISK_INF, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha, lineend = "round")) # 
+coord.names <- c(coord.names, "inf.whisker.edge")
+}
+if(box.mean == TRUE){
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = stat, mapping = ggplot2::aes_string(x = "X", y = "MEAN", group = categ[length(categ)]), shape = 23, stroke = box.line.size * 2, fill = stat$COLOR, size = box.mean.size, color = "black", alpha = box.alpha)) # group used in aesthetic to do not have it in the legend
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_polygon(
+data = tempo.diamon.mean, 
+mapping = ggplot2::aes(x = X, y = Y, group = GROUP), 
+fill = tempo.diamon.mean[, "COLOR"], 
+color = hsv(0, 0, 0, alpha = box.alpha), # outline of the polygon in black but with alpha
+size = box.line.size, 
+alpha = box.alpha
+))
+coord.names <- c(coord.names, "mean")
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = if(box.notch == FALSE){X_BOX_INF}else{X_NOTCH_INF}, xend = if(box.notch == FALSE){X_BOX_SUP}else{X_NOTCH_SUP}, y = MEDIAN, yend = MEDIAN, group = categ[length(categ)]), color = "black", size = box.line.size * 2, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "median")
+}
+# end boxplot display before dot display if box.fill = TRUE
+
+
+
+
+
+
+# dot display
+if( ! is.null(dot.color)){
+if(dot.tidy == FALSE){
+if(is.null(dot.categ)){
+if(dot.border.size == 0){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
+data = dot.coord.rd3, 
+mapping = ggplot2::aes_string(x = "dot.x", y = "y", group = categ[length(categ)]), 
+size = dot.size, 
+shape = 19, 
+color = dot.coord.rd3$dot.color, 
+alpha = dot.alpha
+)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
+}else{
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
+data = dot.coord.rd3, 
+mapping = ggplot2::aes_string(x = "dot.x", y = "y", group = categ[length(categ)]), 
+shape = 21, 
+stroke = dot.border.size, 
+color = if(is.null(dot.border.color)){dot.coord.rd3$dot.color}else{rep(dot.border.color, nrow(dot.coord.rd3))}, 
+size = dot.size, 
+fill = dot.coord.rd3$dot.color, 
+alpha = dot.alpha
+)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
+}
+}else{
+if(dot.border.size == 0){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
+data = dot.coord.rd3, 
+mapping = ggplot2::aes_string(x = "dot.x", y = "y", alpha = dot.categ), 
+size = dot.size, 
+shape = 19, 
+color = dot.coord.rd3$dot.color
+)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
+}else{
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
+data = dot.coord.rd3, 
+mapping = ggplot2::aes_string(x = "dot.x", y = "y", alpha = dot.categ), 
+size = dot.size, 
+shape = 21, 
+stroke = dot.border.size, 
+color = if(is.null(dot.border.color)){dot.coord.rd3$dot.color}else{rep(dot.border.color, nrow(dot.coord.rd3))}, 
+fill = dot.coord.rd3$dot.color
+)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = dot.legend.name, values = rep(dot.alpha, length(dot.categ.class.order)), guide = ggplot2::guide_legend(override.aes = list(fill = dot.color, color = if(is.null(dot.border.color)){dot.color}else{dot.border.color}, stroke = dot.border.size, alpha = dot.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+}
+coord.names <- c(coord.names, "dots")
+}else if(dot.tidy == TRUE){
+# here plot using group -> no scale
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_dotplot(
+data = dot.coord, 
+mapping = ggplot2::aes_string(x = categ[1], y = "y", group = "group"), # not dot.categ here because the classes of dot.categ create new separations
+position = ggplot2::position_dodge(width = box.width), 
+binpositions = "all", 
+binaxis = "y", 
+stackdir = "center", 
+alpha = dot.alpha, 
+fill = dot.coord$dot.color, 
+stroke = dot.border.size, 
+color = if(is.null(dot.border.color)){dot.coord$dot.color}else{rep(dot.border.color, nrow(dot.coord))}, 
+show.legend = FALSE, # WARNING: do not use show.legend = TRUE because it uses the arguments outside aes() as aesthetics (here color and fill). Thus I must find a way using ggplot2::scale_discrete_manual()
+binwidth = (y.lim[2] - y.lim[1]) / dot.tidy.bin.nb
+)) # geom_dotplot ggplot2 v3.3.0: I had to remove rev() in fill and color # very weird behavior of geom_dotplot ggplot2 v3.2.1, (1) because with aes group = (to avoid legend), the dot plotting is not good in term of coordinates, and (2) because data1 seems reorderer according to x = categ[1] before plotting. Thus, I have to use fill = dot.coord[rev(order(dot.coord[, categ[1]], decreasing = TRUE)), "dot.color"] to have the good corresponding colors # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
+coord.names <- c(coord.names, "dots")
+if( ! is.null(dot.categ)){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_dotplot(
+data = dot.coord, 
+mapping = ggplot2::aes_string(x = categ[1], y = "y", alpha = dot.categ), # not dot.categ here because the classes of dot.categ create new separations
+position = ggplot2::position_dodge(width = box.width), 
+binpositions = "all", 
+binaxis = "y", 
+stackdir = "center", 
+fill = NA, 
+stroke = NA, 
+color = NA, 
+# WARNING: do not use show.legend = TRUE because it uses the arguments outside aes() as aesthetics (here color and fill). Thus I must find a way using ggplot2::scale_discrete_manual()
+binwidth = (y.lim[2] - y.lim[1]) / dot.tidy.bin.nb
+)) # geom_dotplot ggplot2 v3.3.0: I had to remove rev() in fill and color # very weird behavior of geom_dotplot ggplot2 v3.2.1, (1) because with aes group = (to avoid legend), the dot plotting is not good in term of coordinates, and (2) because data1 seems reorderer according to x = categ[1] before plotting. Thus, I have to use fill = dot.coord[rev(order(dot.coord[, categ[1]], decreasing = TRUE)), "dot.color"] to have the good corresponding colors # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "linetype", name = dot.legend.name, values = rep(1, length(categ.color)))) # values = rep("black", length(categ.color)) are the values of color (which is the border color of dots), and this modify the border color on the plot. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+coord.names <- c(coord.names, "bad_remove")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = dot.legend.name, values = rep(dot.alpha, length(dot.categ.class.order)), labels = dot.categ.class.order, guide = ggplot2::guide_legend(title = if(ini.dot.categ == categ[length(categ)]){dot.categ}else{ini.dot.categ}, override.aes = list(fill = levels(dot.coord$dot.color), color = if(is.null(dot.border.color)){levels(dot.coord$dot.color)}else{dot.border.color}, stroke = dot.border.size, alpha = dot.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+}
+# coordinates of tidy dots
+tempo.coord <- ggplot2::ggplot_build(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "))))$data # to have the tidy dot coordinates
+if(length(which(sapply(X = tempo.coord, FUN = function(X){any(names(X) == "binwidth", na.rm = TRUE)}))) != 1){ # detect the compartment of tempo.coord which is the binned data frame
+# if(length(which(sapply(tempo.coord, FUN = nrow) == nrow(data1))) > if(is.null(dot.categ)){1}else{2}){ # this does not work if only one dot per class, thus replaced by above # if(is.null(dot.categ)){1}else{2} because 1 dotplot if dot.categ is NULL and 2 dotplots if not, with the second being a blank dotplot with wrong coordinates. Thus take the first in that situation
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nEITHER MORE THAN 1 OR NO COMPARTMENT HAVING A DATA FRAME WITH binwidth AS COLUMN NAME IN THE tempo.coord LIST (FOR TIDY DOT COORDINATES). CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+# dot.coord.tidy1 <- tempo.coord[[which(sapply(tempo.coord, FUN = nrow) == nrow(data1))[1]]] # this does not work if only one dot per class, thus replaced by above # the second being a blank dotplot with wrong coordinates. Thus take the first whatever situation
+dot.coord.tidy1 <- tempo.coord[[which(sapply(X = tempo.coord, FUN = function(X){any(names(X) == "binwidth", na.rm = TRUE)}))]] # detect the compartment of tempo.coord which is the binned data frame
+dot.coord.tidy1$x <- as.numeric(dot.coord.tidy1$x) # because weird class
+dot.coord.tidy1$PANEL <- as.numeric(dot.coord.tidy1$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
+}
+# tempo.box.coord <- merge(box.coord, unique(dot.coord[, c("PANEL", "group", categ)]), by = c("PANEL", "group"), sort = FALSE) # not required anymore because box.coord already contains categ do not add dot.categ and tidy_group_coord here because the coordinates are for stats. Add the categ in box.coord. WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in box.coord. Thus, no need to consider fill column
+# below inactivated because not true when dealing with dot.categ different from categ
+# if(nrow(tempo.box.coord) != nrow(box.coord)){
+# tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT tempo.box.coord DATA FRAME. CODE HAS TO BE MODIFIED")
+# stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+# }
+dot.coord.tidy2 <- merge(dot.coord.tidy1, box.coord[c("fill", "PANEL", "group", "x", categ)], by = c("PANEL", "group"), sort = FALSE) # send the coord of the boxes into the coord data.frame of the dots (in the column x.y).WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in tempo.box.coord. Thus, no need to consider fill colum # DANGER: from here the fill.y and x.y (from tempo.box.coord) are not good in dot.coord.tidy2. It is ok because Categ1 Categ2 from tempo.box.coord are ok with the group column from dot.coord.tidy1. This is due to the fact that dot.coord.tidy resulting from geom_dotplot does not make the same groups as the other functions
+if(nrow(dot.coord.tidy2) != nrow(dot.coord)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.tidy2 DATA FRAME. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# From here, check for dot.coord.tidy3 which wil be important for stat over the plot. WARNING: dot.categ has nothing to do here for stat coordinates. Thus, not in tempo.data1
+if(length(categ)== 1L){
+tempo.data1 <- unique(data.frame(data1[categ[1]], group = as.integer(data1[, categ[1]]), stringsAsFactors = TRUE)) # categ[1] is factor
+names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
+verif <- paste0(categ[1], ".check")
+}else if(length(categ) == 2L){
+tempo.data1 <- unique(
+data.frame(
+data1[c(categ[1], categ[2])], 
+group = as.integer(factor(paste0(
+formatC(as.integer(data1[, categ[2]]), width = nchar(max(as.integer(data1[, categ[2]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
+".", 
+formatC(as.integer(data1[, categ[1]]), width = nchar(max(as.integer(data1[, categ[1]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
+)), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
+)
+) # categ[2] first if categ[2] is used to make the categories in ggplot and categ[1] is used to make the x-axis
+names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
+names(tempo.data1)[names(tempo.data1) == categ[2]] <- paste0(categ[2], ".check")
+verif <- c(paste0(categ[1], ".check"), paste0(categ[2], ".check"))
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+dot.coord.tidy3 <- merge(dot.coord.tidy2, tempo.data1, by = intersect("group", "group"), sort = FALSE) # send the factors of data1 into coord. WARNING: I have tested intersect("group", "group") instead of by = "group". May be come back to by = "group" in case of error. But I did this because of an error in dot.coord.rd3 above
+if(nrow(dot.coord.tidy3) != nrow(dot.coord) | ( ! fun_comp_2d(dot.coord.tidy3[categ], dot.coord.tidy3[verif])$identical.content)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.tidy3 DATA FRAME. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end coordinates of tidy dots
+}
+}
+# end dot display
+
+
+
+# boxplot display (if box.fill = FALSE, otherwise, already plotted above)
+if(box.fill == TRUE){
+# overcome "work only for the filling of boxes, not for the frame. See https://github.com/tidyverse/ggplot2/issues/252"
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color}, guide = ggplot2::guide_legend(order = 1))) #, guide = ggplot2::guide_legend(override.aes = list(fill = levels(tempo.polygon$COLOR), color = "black")))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = rep(hsv(0, 0, 0, alpha = box.alpha), length(unique(data1[, categ[length(categ)]]))), guide = ggplot2::guide_legend(order = 1))) # , guide = ggplot2::guide_legend(override.aes = list(color = "black", alpha = box.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor # outline of the polygon in black but with alpha
+}else{
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[length(categ)], fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, size = box.line.size, notch = box.notch, alpha = box.alpha, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}, outlier.shape = if( ! is.null(dot.color)){NA}else{21}, outlier.color = if( ! is.null(dot.color)){NA}else{if(dot.border.size == 0){NA}else{dot.border.color}}, outlier.fill = if( ! is.null(dot.color)){NA}else{NULL}, outlier.size = if( ! is.null(dot.color)){NA}else{dot.size}, outlier.stroke = if( ! is.null(dot.color)){NA}else{dot.border.size}, outlier.alpha = if( ! is.null(dot.color)){NA}else{dot.alpha})) # the color, size, etc. of the outliers are dealt here. outlier.color = NA to do not plot outliers when dots are already plotted
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_path(
+data = tempo.polygon, 
+mapping = ggplot2::aes_string(x = "X", y = "Y", group = "BOX", color = categ[length(categ)]), 
+size = box.line.size, 
+alpha = box.alpha, 
+lineend = "round", 
+linejoin = "round"
+))
+coord.names <- c(coord.names, "main.box")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = if(box.notch == FALSE){X_BOX_INF}else{X_NOTCH_INF}, xend = if(box.notch == FALSE){X_BOX_SUP}else{X_NOTCH_SUP}, y = MEDIAN, yend = MEDIAN, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size * 2, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "median")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "sup.whisker")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_INF, yend = WHISK_INF, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha)) # 
+coord.names <- c(coord.names, "inf.whisker")
+if(box.whisker.width > 0){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha, lineend = "round")) # 
+coord.names <- c(coord.names, "sup.whisker.edge")
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_INF, yend = WHISK_INF, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha, lineend = "round")) # 
+coord.names <- c(coord.names, "inf.whisker.edge")
+}
+if(box.mean == TRUE){
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = stat, mapping = ggplot2::aes_string(x = "X", y = "MEAN", group = categ[length(categ)]), shape = 23, stroke = box.line.size * 2, color = stat$COLOR, size = box.mean.size, fill = NA, alpha = box.alpha)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_path(
+data = tempo.diamon.mean, 
+mapping = ggplot2::aes(x = X, y = Y, group = GROUP), 
+color = tempo.diamon.mean[, "COLOR"], 
+size = box.line.size, 
+alpha = box.alpha, 
+lineend = "round", 
+linejoin = "round"
+))
+coord.names <- c(coord.names, "mean")
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = rep(NA, length(unique(data1[, categ[length(categ)]]))))) #, guide = ggplot2::guide_legend(override.aes = list(color = categ.color)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color}, guide = ggplot2::guide_legend(override.aes = list(alpha = if(plot == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list()) == 0L & Sys.info()["sysname"] == "Windows"))){1}else{box.alpha})))) # , guide = ggplot2::guide_legend(override.aes = list(color = as.character(categ.color))))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
+if(plot == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list()) == 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+# to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(box.alpha == 0){ # remove box legend because no boxes drawn
+# add this after the scale_xxx_manual() for boxplots
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE)) # inactivate the legend
+}
+# end boxplot display (if box.fill = FALSE, otherwise, already plotted above)
+
+
+
+
+# stat display
+# layer after dots but ok, behind dots on the plot
+if( ! is.null(stat.pos)){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NUMBERS DISPLAYED ARE ", ifelse(stat.mean == FALSE, "MEDIANS", "MEANS"))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+if(stat.pos == "top"){
+tempo.stat <- data.frame(stat, Y = y.lim[2], stringsAsFactors = TRUE) # I had to create a data frame for geom_tex() so that facet is taken into account, (ggplot2::annotate() does not deal with facet because no data and mapping arguments). Of note, facet.categ is in tempo.stat, via tempo.mean, via dot.coord
+if(stat.mean == FALSE){tempo.stat$MEDIAN <- formatC(stat.nolog$MEDIAN, digit = 2, drop0trailing = TRUE, format = "f")}else{tempo.stat$MEAN <- formatC(stat.nolog$MEAN, digit = 2, drop0trailing = TRUE, format = "f")}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
+data = tempo.stat, 
+mapping = ggplot2::aes_string(x = "X", y = "Y", label = ifelse(stat.mean == FALSE, "MEDIAN", "MEAN")),
+size = stat.size, 
+color = "black", 
+angle = stat.angle, 
+hjust = stat.just$hjust, 
+vjust = stat.just$vjust
+)) # stat$X used here because identical to stat.nolog but has the X. WARNING: no need of order() for labels because box.coord$x set the order. For justification, see https://stackoverflow.com/questions/7263849/what-do-hjust-and-vjust-do-when-making-a-plot-using-ggplot
+coord.names <- c(coord.names, "stat.pos")
+}else if(stat.pos == "above"){
+# stat coordinates
+if( ! is.null(dot.color)){ # for text just above max dot
+if(dot.tidy == FALSE){
+tempo.stat.ini <- dot.coord.rd3
+}else if(dot.tidy == TRUE){
+tempo.stat.ini <- dot.coord.tidy3
+tempo.stat.ini$x.y <- tempo.stat.ini$x.x # this is just to be able to use tempo.stat.ini$x.y for untidy or tidy dots (remember that dot.coord.tidy3$x.y is not good, see above)
+}
+stat.coord1 <- aggregate(x = tempo.stat.ini["y"], by = {x.env <- if(length(categ)== 1L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]])}else if(length(categ) == 2L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]], tempo.stat.ini[, categ[2]])} ; names(x.env) <- if(length(categ)== 1L){c("group", "PANEL", "x.y", categ[1])}else if(length(categ) == 2L){c("group", "PANEL", "x.y", categ[1], categ[2])} ; x.env}, FUN = min, na.rm = TRUE)
+names(stat.coord1)[names(stat.coord1) == "y"] <- "dot.min"
+stat.coord2 <- aggregate(x = tempo.stat.ini["y"], by = {x.env <- if(length(categ)== 1L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]])}else if(length(categ) == 2L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]], tempo.stat.ini[, categ[2]])} ; names(x.env) <- if(length(categ)== 1L){c("group", "PANEL", "x.y", categ[1])}else if(length(categ) == 2L){c("group", "PANEL", "x.y", categ[1], categ[2])} ; x.env}, FUN = max, na.rm = TRUE)
+names(stat.coord2) <- paste0(names(stat.coord2), "_from.dot.max")
+names(stat.coord2)[names(stat.coord2) == "y_from.dot.max"] <- "dot.max"
+stat.coord3 <- cbind(box.coord[order(box.coord$group, box.coord$PANEL), ], stat.coord1[order(stat.coord1$group, stat.coord1$x.y), ], stat.coord2[order(stat.coord2$group, stat.coord2$x.y), ], stringsAsFactors = TRUE) # 
+if( ! all(identical(round(stat.coord3$x, 9), round(as.numeric(stat.coord3$x.y), 9)), na.rm = TRUE)){ # as.numeric() because stat.coord3$x is class "mapped_discrete" "numeric"
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nFUSION OF box.coord, stat.coord1 AND stat.coord2 ACCORDING TO box.coord$x, stat.coord1$x.y AND stat.coord2$x.y IS NOT CORRECT. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# text.coord <- stat.coord3[, c("x", "group", "dot.min", "dot.max")]
+# names(text.coord)[names(text.coord) == "dot.min"] <- "text.min.pos"
+#names(text.coord)[names(text.coord) == "dot.max"] <- "text.max.pos"
+box.coord <- box.coord[order(box.coord$x, box.coord$group, box.coord$PANEL), ]
+# text.coord <- text.coord[order(text.coord$x), ] # to be sure to have the two objects in the same order for x. WARNING: cannot add identical(as.integer(text.coord$group), as.integer(box.coord$group)) because with error, the correspondence between x and group is not the same
+stat.coord3 <- stat.coord3[order(stat.coord3$x, stat.coord3$group, stat.coord3$PANEL), ] # to be sure to have the two objects in the same order for x. WARNING: cannot add identical(as.integer(text.coord$group), as.integer(box.coord$group)) because with error, the correspondence between x and group is not the same
+if( ! (identical(box.coord$x, stat.coord3$x) & identical(box.coord$group, stat.coord3$group) & identical(box.coord$PANEL, stat.coord3$PANEL))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\ntext.coord AND box.coord DO NOT HAVE THE SAME x, group AND PANEL COLUMN CONTENT")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}else{
+stat.coord3 <- box.coord
+}
+stat.coord3 <- data.frame(
+stat.coord3, 
+Y = stat.coord3[, ifelse(
+is.null(dot.color), 
+ifelse(diff(y.lim) > 0, "ymax", "ymin"), 
+ifelse(diff(y.lim) > 0, "ymax_final", "ymin_final")
+)], 
+stringsAsFactors = TRUE
+) # ymax is top whisker, ymax_final is top dot
+# stat.coord3 <- data.frame(stat.coord3, Y = vector("numeric", length = nrow(stat.coord3)), stringsAsFactors = TRUE)
+# check.Y <- as.logical(stat.coord3$Y) # convert everything in Y into FALSE (because Y is full of zero)
+# end stat coordinates
+# stat display
+# performed twice: first for y values >=0, then y values < 0, because only a single value allowed for hjust anf vjust
+if(stat.mean == FALSE){
+tempo.center.ref <- "middle"
+}else{
+tempo.center.ref <- "MEAN"
+}
+# if(is.null(dot.color)){
+# tempo.low.ref <- "ymin"
+# tempo.high.ref <- "ymax"
+# }else{
+# tempo.low.ref <- "ymin_final"
+# tempo.high.ref <- "ymax_final"
+# }
+# tempo.log.high <- if(diff(y.lim) > 0){stat.coord3[, tempo.center.ref] >= 0}else{stat.coord3[, tempo.center.ref] < 0}
+# tempo.log.low <- if(diff(y.lim) > 0){stat.coord3[, tempo.center.ref] < 0}else{stat.coord3[, tempo.center.ref] >= 0}
+# stat.coord3$Y[tempo.log.high] <- stat.coord3[tempo.log.high, tempo.high.ref]
+# stat.coord3$Y[tempo.log.low] <- stat.coord3[tempo.log.low, tempo.low.ref]
+# add distance
+stat.coord3$Y <- stat.coord3$Y + diff(y.lim) * stat.dist / 100
+# end add distance
+# correct median or mean text format
+if(y.log != "no"){
+stat.coord3[, tempo.center.ref] <- ifelse(y.log == "log2", 2, 10)^(stat.coord3[, tempo.center.ref])
+}
+stat.coord3[, tempo.center.ref] <- formatC(stat.coord3[, tempo.center.ref], digit = 2, drop0trailing = TRUE, format = "f")
+# end correct median or mean text format
+# if(any(tempo.log.high) == TRUE){
+# tempo.stat <- stat.coord3[tempo.log.high,]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
+data = stat.coord3, 
+mapping = ggplot2::aes_string(x = "x", y = "Y", label = tempo.center.ref),
+size = stat.size, 
+color = "black", 
+angle = stat.angle, 
+hjust = stat.just$hjust, 
+vjust = stat.just$vjust
+)) # WARNING: no need of order() for labels because box.coord$x set the order
+coord.names <- c(coord.names, "stat.pos")
+# }
+# if(any(tempo.log.low) == TRUE){
+# tempo.stat <- stat.coord3[tempo.log.low,]
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
+# data = tempo.stat, 
+# mapping = ggplot2::aes_string(x = "x", y = "Y", label = tempo.center.ref),
+# size = stat.size, 
+# color = "black", 
+# hjust = ifelse(vertical == TRUE, 0.5, 0.5 + stat.dist), 
+# vjust = ifelse(vertical == TRUE, 0.5 + stat.dist, 0.5)
+# )) # WARNING: no need of order() for labels because box.coord$x set the order
+# coord.names <- c(coord.names, "stat.pos.negative")
+# }
+# end stat display
+}else{
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 5")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+}
+# end stat display
+# legend management
+if(legend.show == FALSE){ # must be here because must be before bef.final.plot <- 
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE, alpha = FALSE)) # inactivate the initial legend
+}
+# end legend management
+
+
+
+# y scale management (cannot be before dot plot management)
+# the rescaling aspect is complicated and not intuitive. See:
+# explaination: https://github.com/tidyverse/ggplot2/issues/3948
+# the oob argument of scale_y_continuous() https://ggplot2.tidyverse.org/reference/scale_continuous.html
+# see also https://github.com/rstudio/cheatsheets/blob/master/data-visualization-2.1.pdf
+# secondary ticks
+bef.final.plot <- ggplot2::ggplot_build(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + if(vertical == TRUE){ggplot2::scale_y_continuous(expand = c(0, 0), limits = sort(y.lim), oob = scales::rescale_none)}else{ggplot2::coord_flip(ylim = y.lim)}')))) # here I do not need the x-axis and y-axis orientation, I just need the number of main ticks and the legend. I DI NOT UNDERSTAND THE COMMENT HERE BECAUSE WE NEED COORD_FLiP
+tempo.coord <- bef.final.plot$layout$panel_params[[1]]
+# y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non NULL or if y.log argument is different from "no")
+if(y.log != "no"){ # integer main ticks for log2 and log10
+tempo.scale <- (as.integer(min(y.lim, na.rm = TRUE)) - 1):(as.integer(max(y.lim, na.rm = TRUE)) + 1)
+}else{
+tempo <- if(is.null(attributes(tempo.coord$y$breaks))){tempo.coord$y$breaks}else{unlist(attributes(tempo.coord$y$breaks))}
+if(all(is.na(tempo))){# all() without na.rm -> ok because is.na() cannot be NA
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$y$breaks")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+tempo.scale <- fun_scale(lim = y.lim, n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks. If fact: n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) replaced by n = ifelse(is.null(y.tick.nb), 4, y.tick.nb))
+}
+y.second.tick.values <- NULL
+y.second.tick.pos <- NULL
+if(y.log != "no"){
+tempo <- fun_inter_ticks(lim = y.lim, log = y.log)
+y.second.tick.values <- tempo$values
+y.second.tick.pos <- tempo$coordinates
+# if(vertical == TRUE){ # do not remove in case the bug is fixed
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", y = y.second.tick.pos, yend = y.second.tick.pos, x = tempo.coord$x.range[1], xend = tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80))
+# }else{ # not working because of the ggplot2 bug
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", x = y.second.tick.pos, xend = y.second.tick.pos, y = tempo.coord$y.range[1], yend = tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80))
+# }
+coord.names <- c(coord.names, "y.second.tick.positions")
+}else if(( ! is.null(y.second.tick.nb)) & y.log == "no"){
+# if(y.second.tick.nb > 0){ #inactivated because already checked before
+if(length(tempo.scale) < 2){
+tempo.cat1 <- c("y.tick.nb", "y.second.tick.nb")
+tempo.cat2 <- sapply(list(y.tick.nb, y.second.tick.nb), FUN = paste0, collapse = " ")
+tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE Y-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+tempo <- fun_inter_ticks(lim = y.lim, log = y.log, breaks = tempo.scale, n = y.second.tick.nb)
+}
+y.second.tick.values <- tempo$values
+y.second.tick.pos <- tempo$coordinates
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
+geom = "segment", 
+y = y.second.tick.pos, 
+yend = y.second.tick.pos, 
+x = if(vertical == TRUE){tempo.coord$x.range[1]}else{tempo.coord$y.range[1]}, 
+xend = if(vertical == TRUE){tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80}else{tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80}
+))
+coord.names <- c(coord.names, "y.second.tick.positions")
+}
+# end y.second.tick.positions
+# for the ggplot2 bug with y.log, this does not work: eval(parse(text = ifelse(vertical == FALSE & y.log == "log10", "ggplot2::scale_x_continuous", "ggplot2::scale_y_continuous")))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_y_continuous(
+breaks = tempo.scale, 
+minor_breaks = y.second.tick.pos, 
+labels = if(y.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(y.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(y.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 6") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, # == in stop() to be able to add several messages between ==
+expand = c(0, 0), # remove space after after axis limits
+limits = sort(y.lim), # NA indicate that limits must correspond to data limits but ylim() already used
+oob = scales::rescale_none, 
+trans = ifelse(diff(y.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_y_reverse() but create the problem of y-axis label disappearance with y.lim decreasing. Thus, do not use. Use ylim() below and after this
+))
+if(vertical == TRUE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_cartesian(ylim = y.lim)) # problem of ggplot2::ylim() is that it redraws new breaks # coord_cartesian(ylim = y.lim)) not used because bug -> y-axis label disappearance with y.lim decreasing I DO NOT UNDERSTAND THIS MESSAGE WHILE I USE COORD_CARTESIAN # clip = "off" to have secondary ticks outside plot region does not work
+}else{
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_flip(ylim = y.lim)) # clip = "off" to have secondary ticks outside plot region does not work # create the problem of y-axis label disappearance with y.lim decreasing. IDEM ABOVE
+
+}
+# end y scale management (cannot be before dot plot management)
+
+
+# legend management
+if( ! is.null(legend.width)){
+legend.final <- fun_gg_get_legend(ggplot_built = bef.final.plot, fun.name = function.name, lib.path = lib.path) # get legend
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE, alpha = FALSE)) # inactivate the initial legend
+if(is.null(legend.final) & plot == TRUE){ # even if any(unlist(legend.disp)) is TRUE
+legend.final <- ggplot2::ggplot()+ggplot2::theme_void() # empty graph instead of legend
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON NULL legend.width ARGUMENT\n")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end legend management
+
+
+# drawing
+fin.plot <- suppressMessages(suppressWarnings(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))))
+grob.save <- NULL
+if(plot == TRUE){
+# following lines inactivated because of problem in warn.recov and message.recov
+# assign("env_fun_get_message", new.env())
+# assign("tempo.gg.name", tempo.gg.name, envir = env_fun_get_message)
+# assign("tempo.gg.count", tempo.gg.count, envir = env_fun_get_message)
+# assign("add", add, envir = env_fun_get_message)
+# two next line: for the moment, I cannot prevent the warning printing
+# warn.recov <- fun_get_message(paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}), kind = "warning", header = FALSE, print.no = FALSE, env = env_fun_get_message) # for recovering warnings printed by ggplot() functions
+# message.recov <- fun_get_message('print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))', kind = "message", header = FALSE, print.no = FALSE, env = env_fun_get_message) # for recovering messages printed by ggplot() functions
+# if( ! (return == TRUE & return.ggplot == TRUE)){ # because return() plots when return.ggplot is TRUE # finally not used -> see return.ggplot description
+if(is.null(legend.width)){
+grob.save <- suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot)))
+}else{
+grob.save <-suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
+}
+# }
+# suppressMessages(suppressWarnings(print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))))
+}else{
+# following lines inactivated because of problem in warn.recov and message.recov
+# message.recov <- NULL
+# warn.recov <- NULL
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end drawing
+
+
+
+# output
+# following lines inactivated because of problem in warn.recov and message.recov
+# if( ! (is.null(warn) & is.null(warn.recov) & is.null(message.recov))){
+# warn <- paste0(warn, "\n\n", if(length(warn.recov) > 0 | length(message.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", ifelse( ! is.null(warn.recov), unique(message.recov), ""), ifelse( ! is.null(message.recov), unique(message.recov), ""), collapse = "\n\n"), "\n\n")})
+# }else if( ! (is.null(warn) & is.null(warn.recov)) & is.null(message.recov)){
+# warn <- paste0(warn, "\n\n", if(length(warn.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", unique(warn.recov), collapse = "\n\n"), "\n\n")})
+# }else if( ! (is.null(warn) & is.null(message.recov)) & is.null(warn.recov)){
+# warn <- paste0(warn, "\n\n", if(length(message.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", unique(message.recov), collapse = "\n\n"), "\n\n")})
+# }
+if(warn.print == TRUE & ! is.null(warn)){
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+}
+on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
+if(return == TRUE){
+tempo.output <- ggplot2::ggplot_build(fin.plot)
+tempo.output$data <- tempo.output$data[-1] # remove the first data because corresponds to the initial empty boxplot
+if(length(tempo.output$data) != length(coord.names)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nlength(tempo.output$data) AND length(coord.names) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+names(tempo.output$data) <- coord.names
+tempo.output$data <- tempo.output$data[coord.names != "bad_remove"]
+}
+tempo <- tempo.output$layout$panel_params[[1]]
+output <- list(
+data = data1.ini, 
+stat = stat.nolog, 
+removed.row.nb = removed.row.nb, 
+removed.rows = removed.rows, 
+plot = c(tempo.output$data, y.second.tick.values = list(y.second.tick.values)), 
+panel = facet.categ, 
+axes = list(
+x.range = tempo$x.range, 
+x.labels = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{tempo$x$scale$get_labels()}, # is.null(attributes(tempo$x$breaks)) test if it is number (TRUE) or character (FALSE)
+x.positions = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{unlist(attributes(tempo$x$breaks))}, 
+y.range = tempo$y.range, 
+y.labels = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{tempo$y$scale$get_labels()}, 
+y.positions = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{unlist(attributes(tempo$y$breaks))}
+), 
+warn = paste0("\n", warn, "\n\n"), 
+ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL}, # fin.plot plots the graph if return == TRUE
+gtable = if(return.gtable == TRUE){grob.save}else{NULL} 
+)
+return(output) # this plots the graph if return.ggplot is TRUE and if no assignment
+}
+# end output
+# end main code
+}
+
+
+
+
+
+
+
+
+
+# add density
+# rasterise all kind: https://cran.r-project.org/web/packages/ggrastr/vignettes/Raster_geoms.html
+# log not good: do not convert as in boxplot
+
+
+fun_gg_scatter <- function(
+data1, 
+x, 
+y, 
+categ = NULL, 
+categ.class.order = NULL, 
+color = NULL, 
+geom = "geom_point", 
+geom.step.dir = "hv", 
+geom.stick.base = NULL, 
+alpha = 0.5, 
+dot.size = 2, 
+dot.shape = 21, 
+dot.border.size = 0.5, 
+dot.border.color = NULL, 
+line.size = 0.5, 
+line.type = "solid", 
+x.lim = NULL, 
+x.lab = NULL, 
+x.log = "no", 
+x.tick.nb = NULL, 
+x.second.tick.nb = NULL, 
+x.include.zero = FALSE, 
+x.left.extra.margin = 0.05, 
+x.right.extra.margin = 0.05, 
+x.text.angle = 0, 
+y.lim = NULL, 
+y.lab = NULL, 
+y.log = "no", 
+y.tick.nb = NULL, 
+y.second.tick.nb = NULL, 
+y.include.zero = FALSE, 
+y.top.extra.margin = 0.05, 
+y.bottom.extra.margin = 0.05, 
+y.text.angle = 0, 
+raster = FALSE, 
+raster.ratio = 1, 
+raster.threshold = NULL, 
+text.size = 12, 
+title = "", 
+title.text.size = 12, 
+legend.show = TRUE, 
+legend.width = 0.5, 
+legend.name = NULL, 
+article = TRUE, 
+grid = FALSE, 
+add = NULL, 
+return = FALSE, 
+return.ggplot = FALSE,
+return.gtable = TRUE,
+plot = TRUE, 
+warn.print = FALSE, 
+lib.path = NULL
+){
+# AIM
+# Plot ggplot2 scatterplot with the possibility to overlay dots from up to 3 different data frames (-> three different legends) and lines from up to 3 different data frames (-> three different legends) -> up to 6 overlays totally
+# For ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
+# WARNINGS
+# Rows containing NA in data1[, c(x, y, categ)] will be removed before processing, with a warning (see below)
+# Size arguments (dot.size, dot.border.size, line.size, text.size and title.text.size) are in mm. See Hadley comment in https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size. See also http://sape.inf.usi.ch/quick-reference/ggplot2/size). Unit object are not accepted, but conversion can be used (e.g., grid::convertUnit(grid::unit(0.2, "inches"), "mm", valueOnly = TRUE))
+# ARGUMENTS
+# data1: a dataframe compatible with ggplot2, or a list of data frames. Order matters for the order of the legend and for the layer staking (starting from below to top)
+# x: single character string of the data1 column name for x-axis coordinates. If data1 is a list, then x must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Write NULL for each "geom_hline" in geom argument
+# y: single character string of the data1 column name for y-axis coordinates. If data1 is a list, then y must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Write NULL for each "geom_vline" in geom argument
+# categ: either NULL or a single character string or a list of single character strings, indicating the data1 column names to use for categories which creates legend display
+# If categ == NULL, no categories -> no legend displayed
+# If data1 is a data frame, categ must be a single character string of the data1 column name for categories
+# If data1 is a list, then categ must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL (no legend display for these compartments), and other not
+# categ.class.order: either (1) NULL or (2) a vector of character strings or (3) a list of these vectors, setting the order of the classes of categ in the legend display
+# If categ.class.order is NULL, classes are represented according to the alphabetical order
+# If data1 is a data frame, categ.class.order must be a vector of character strings specifying the different classes in the categ column name of data1
+# If data1 is a list, then categ.class.order must be a list of vector of character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL (alphabetical order for these compartments), and other not
+# color: either (1) NULL, or (2) a vector of character strings or integers, or (3) a list of vectors of character strings or integers
+# If color is NULL, default colors of ggplot2
+# If data1 is a data frame, color argument can be either:
+# (1) a single color string. All the dots of the corresponding data1 will have this color, whatever the categ value (NULL or not)
+# (2) if categ is non-null, a vector of string colors, one for each class of categ. Each color will be associated according to the categ.class.order argument if specified, or to the alphabetical order of categ classes otherwise
+# (3) if categ is non-null, a vector or factor of string colors, like if it was one of the column of data1 data frame. WARNING: a single color per class of categ and a single class of categ per color must be respected
+# Positive integers are also accepted instead of character strings, as long as above rules about length are respected. Integers will be processed by fun_gg_palette() using the max integer value among all the integers in color (see fun_gg_palette())
+# If data1 is a list, then color argument must be either: 
+# (1) a list of character strings or integers, of same size as data1, with compartment 1 related to compartment 1 of data1, etc.
+# (2) a single character string or a single integer
+# With a list (first possibility), the rules described for when data1 is a data frame apply to each compartment of the list. Some of the compartments can be NULL. In that case, a different grey color will be used for each NULL compartment. With a single value (second possibility), the same color will be used for all the dots and lines, whatever the data1 list
+# geom: single character string of the kind of plot, or a list of single character strings
+# Either:
+# "geom_point" (scatterplot)
+# "geom_line" (coordinates plotted then line connection, from the lowest to highest x coordinates first and from the lowest to highest y coordinates thenafter)
+# "geom_path" (coordinates plotted then line connection respecting the row order in data1)
+# "geom_step" coordinates plotted then line connection respecting the row order in data1 but drawn in steps). See the geom.step.dir argument
+# "geom_hline" (horizontal line, no x value provided)
+# "geom_vline" (vertical line, no y value provided)
+# "geom_stick" (dots as vertical bars)
+# If data1 is a list, then geom must be either:
+# (1) a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc.
+# (2) a single character string. In that case the same kind of plot will apply for the different compartments of the data1 list
+# WARNING concerning "geom_hline" or "geom_vline":
+# (1) x or y argument must be NULL, respectively
+# (2) x.lim or y.lim argument must NOT be NULL, respectively, if only these kind of lines are drawn (if other geom present, then x.lim = NULL and y.lim = NULL will generate x.lim and y.lim defined by these other geom, which is not possible with "geom_hline" or "geom_vline" alone)
+# (3) the function will draw n lines for n values in the x argument column name of the data1 data frame. If several colors required, the categ argument must be specified and the corresponding categ column name must exist in the data1 data frame with a different class name for each row
+# geom.step.dir: single character string indicating the direction when using "geom_step" of the geom argument, or a list of single character strings
+# Either:
+# "vh" (vertical then horizontal)
+# "hv" (horizontal then vertical)
+# "mid" (step half-way between adjacent x-values)
+# See https://ggplot2.tidyverse.org/reference/geom_path.html
+# If data1 is a list, then geom.step.dir must be either:
+# (1) a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. The value in compartments related to other geom values than "geom_step" will be ignored
+# (2) a single character string, which will be used for all the "geom_step" values of the geom argument, whatever the data1 list
+# geom.stick.base: either (1) NULL or (2) a single numeric value or (3) a list of single numeric values, setting the base of the sticks when using "geom_stick" of the geom argument
+# If geom.stick.base is NULL, the bottom limit of the y-axis is taken as the base
+# If data1 is a list, then geom.stick.base must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the values in compartments related to other geom values than "geom_stick" will be ignored. With a single value (latter possibility), the same base will be used for all the sticks, whatever the data1 list
+# Warning: the y-axis limits are not modified by the value of geom.stick.base, meaning that this value can be outside of the range of y.lim. Add the value of geom.stick.base also in the y.lim argument if required
+# Warning: if geom.stick.base is NULL, the bottom limit of the y-axis is taken as the base. Thus, be careful with inverted y-axis
+# alpha: single numeric value (from 0 to 1) of transparency. If data1 is a list, then alpha must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. In that case the same transparency will apply for the different compartments of the data1 list
+# dot.size: single numeric value of dot shape radius? in mm. If data1 is a list, then dot.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.size will be used for all the dots, whatever the data1 list
+# dot.shape: value indicating the shape of the dots (see https://ggplot2.tidyverse.org/articles/ggplot2-specs.html) If data1 is a list, then dot.shape must be either (1) a list of single shape values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single shape value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.shape will be used for all the dots, whatever the data1 list
+# dot.border.size: single numeric value of border dot width in mm. Write zero for no dot border. If data1 is a list, then dot.border.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.border.size will be used for all the dots, whatever the data1 list
+# dot.border.color: single character color string defining the color of the dot border (same border color for all the dots, whatever their categories). If dot.border.color == NULL, the border color will be the same as the dot color. A single integer is also accepted instead of a character string, that will be processed by fun_gg_palette()
+# line.size: single numeric value of line width in mm. If data1 is a list, then line.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to dots will be ignored. With a single value (latter possibility), the same line.size will be used for all the lines, whatever the data1 list
+# line.type: value indicating the kind of lines (see https://ggplot2.tidyverse.org/articles/ggplot2-specs.html) If data1 is a list, then line.type must be either (1) a list of single line kind values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single line kind value. With a list (former possibility), the value in compartments related to dots will be ignored. With a single value (latter possibility), the same line.type will be used for all the lines, whatever the data1 list
+# x.lim: 2 numeric values setting the x-axis range. Order of the 2 values matters (for inverted axis). If NULL, the range of the x column name of data1 will be used
+# x.lab: a character string or expression for x-axis label. If NULL, will use the first value of x (x column name of the first data frame in data1). Warning message if the elements in x are different between data frames in data1
+# x.log: either "no", "log2" (values in the x column name of the data1 data frame will be log2 transformed and x-axis will be log2 scaled) or "log10" (values in the x column name of the data1 data frame will be log10 transformed and x-axis will be log10 scaled)
+# x.tick.nb: approximate number of desired values labeling the x-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if x.log is "no", then the number of labeling values is set by ggplot2. If NULL and if x.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the x.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for x.lim = c(9, 1200)). WARNING: if non-NULL and if x.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
+# x.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if x.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$x.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
+# x.include.zero: logical. Does x.lim range include 0? Ignored if x.log is "log2" or "log10"
+# x.left.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to x.lim. If different from 0, add the range of the axis multiplied by x.left.extra.margin (e.g., abs(x.lim[2] - x.lim[1]) * x.left.extra.margin) to the left of x-axis
+# x.right.extra.margin: idem as x.left.extra.margin but to the right of x-axis
+# x.text.angle: integer value of the text angle for the x-axis labeling values, using the same rules as in ggplot2. Use positive value for clockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Use negative values for counterclockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
+# y.lim: 2 numeric values setting the y-axis range. Order of the 2 values matters (for inverted axis). If NULL, the range of the y column name of data1 will be used
+# y.lab: a character string or expression for y-axis label. If NULL, will use the first value of y (y column name of the first data frame in data1). Warning message if the elements in y are different between data frames in data1
+# y.log: either "no", "log2" (values in the y column name of the data1 data frame will be log2 transformed and y-axis will be log2 scaled) or "log10" (values in the y column name of the data1 data frame will be log10 transformed and y-axis will be log10 scaled)
+# y.tick.nb: approximate number of desired values labeling the y-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if y.log is "no", then the number of labeling values is set by ggplot2. If NULL and if y.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the y.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for y.lim = c(9, 1200)). WARNING: if non-NULL and if y.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
+# y.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if y.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$y.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
+# y.include.zero: logical. Does y.lim range include 0? Ignored if y.log is "log2" or "log10"
+# y.top.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to y.lim. If different from 0, add the range of the axis multiplied by y.top.extra.margin (e.g., abs(y.lim[2] - y.lim[1]) * y.top.extra.margin) to the top of y-axis
+# y.bottom.extra.margin: idem as y.top.extra.margin but to the bottom of y-axis
+# y.text.angle: integer value of the text angle for the y-axis labeling values, using the same rules as in ggplot2. Use positive value for clockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Use negative values for counterclockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
+# raster: logical. Dots in raster mode? If FALSE, dots from each "geom_point" from geom argument are plotted in vectorial mode (bigger pdf and long to display if lots of dots). If TRUE, dots from each "geom_point" from geom argument are plotted in matricial mode (smaller pdf and easy display if lots of dots, but it takes time to generate the layer). If TRUE, the raster.ratio argument is used to avoid an ellipsoid representation of the dots. If TRUE, solve the transparency problem with some GUI. Overriden by the non-NULL raster.threshold argument
+# raster.ratio: single numeric value indicating the height / width ratio of the graphic device used (for instance provided by the $dim compartment in the output of the fun_open() function). The default value is 1 because by default R opens a square graphic device. But this argument has to be set when using other device dimensions. Ignored if raster == FALSE
+# raster.threshold: positive integer value indicating the limit of the dot number above which "geom_point" layers from the geom argument switch from vectorial mode to matricial mode (see the raster argument). If any layer is matricial, then the raster.ratio argument is used to avoid an ellipsoid representation of the dots. If non-NULL, it overrides the raster argument
+# text.size: numeric value of the font size of the (1) axis numbers and axis legends and (2) texts in the graphic legend (in mm)
+# title: character string of the graph title
+# title.text.size: numeric value of the title font size in mm
+# legend.show: logical. Show legend? Not considered if categ argument is NULL, because this already generate no legend, excepted if legend.width argument is non-NULL. In that specific case (categ is NULL, legend.show is TRUE and legend.width is non-NULL), an empty legend space is created. This can be useful when desiring graphs of exactly the same width, whatever they have legends or not
+# legend.width: single proportion (between 0 and 1) indicating the relative width of the legend sector (on the right of the plot) relative to the width of the plot. Value 1 means that the window device width is split in 2, half for the plot and half for the legend. Value 0 means no room for the legend, which will overlay the plot region. Write NULL to inactivate the legend sector. In such case, ggplot2 will manage the room required for the legend display, meaning that the width of the plotting region can vary between graphs, depending on the text in the legend
+# legend.name: character string of the legend title. If legend.name is NULL and categ argument is not NULL, then legend.name <- categ. If data1 is a list, then legend.name must be a list of character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL, and other not
+# article: logical. If TRUE, use an article theme (article like). If FALSE, use a classic related ggplot theme. Use the add argument (e.g., add = "+ggplot2::theme_classic()" for the exact classic ggplot theme
+# grid: logical. Draw lines in the background to better read the box values? Not considered if article == FALSE (grid systematically present)
+# add: character string allowing to add more ggplot2 features (dots, lines, themes, facet, etc.). Ignored if NULL
+# WARNING: (1) the string must start with "+", (2) the string must finish with ")" and (3) each function must be preceded by "ggplot2::". Example: "+ ggplot2::coord_flip() + ggplot2::theme_bw()"
+# If the character string contains the "ggplot2::theme" string, then the article argument of fun_gg_scatter() (see above) is ignored with a warning. In addition, some arguments can be overwritten, like x.angle (check all the arguments)
+# Handle the add argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
+# WARNING: the call of objects inside the quotes of add can lead to an error if the name of these objects are some of the fun_gg_scatter() arguments. Indeed, the function will use the internal argument instead of the global environment object. Example article <- "a" in the working environment and add = '+ ggplot2::ggtitle(article)'. The risk here is to have TRUE as title. To solve this, use add = '+ ggplot2::ggtitle(get("article", envir = .GlobalEnv))'
+# return: logical. Return the graph parameters?
+# return.ggplot: logical. Return the ggplot object in the output list? Ignored if return argument is FALSE. WARNING: always assign the fun_gg_scatter() function (e.g., a <- fun_gg_scatter()) if return.ggplot argument is TRUE, otherwise, double plotting is performed. See $ggplot in the RETURN section below for more details
+# return.gtable: logical. Return the ggplot object as gtable of grobs in the output list? Ignored if plot argument is FALSE. Indeed, the graph must be plotted to get the grobs dispositions. See $gtable in the RETURN section below for more details
+# plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
+# warn.print: logical. Print warnings at the end of the execution? ? If FALSE, warning messages are never printed, but can still be recovered in the returned list. Some of the warning messages (those delivered by the internal ggplot2 functions) are not apparent when using the argument plot = FALSE
+# lib.path: character string indicating the absolute path of the required packages (see below). if NULL, the function will use the R library default folders
+# RETURN
+# a scatter plot if plot argument is TRUE
+# a list of the graph info if return argument is TRUE:
+# $data: the initial data with graphic information added. WARNING: if the x.log or y.log argument is not "no", x or y argument column of the data1 data frame are log2 or log10 converted in $data, respectively. Use 2^values or 10^$values to recover the initial values
+# $removed.row.nb: a list of the removed rows numbers in data frames (because of NA). NULL if no row removed
+# $removed.rows: a list of the removed rows in data frames (because of NA). NULL if no row removed
+# $plot: the graphic box and dot coordinates
+# $dots: dot coordinates
+# y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non-null or if y.log argument is different from "no")
+# y.second.tick.values: values of secondary ticks. NULL except if y.second.tick.nb argument is non-null or if y.log argument is different from "no")
+# $panel: the variable names used for the panels (NULL if no panels). WARNING: NA can be present according to ggplot2 upgrade to v3.3.0
+# $axes: the x-axis and y-axis info
+# $warn: the warning messages. Use cat() for proper display. NULL if no warning. WARNING: warning messages delivered by the internal ggplot2 functions are not apparent when using the argument plot = FALSE
+# $ggplot: ggplot object that can be used for reprint (use print($ggplot) or update (use $ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Of note, a non-null $ggplot in the output list is sometimes annoying as the manipulation of this list prints the plot
+# $gtable: gtable object that can be used for reprint (use gridExtra::grid.arrange(...$ggplot) or with additionnal grobs (see the grob decomposition in the examples). NULL if return.ggplot argument is FALSE. Contrary to $ggplot, a non-NULL $gtable in the output list is not annoying as the manipulation of this list does not print the plot
+# REQUIRED PACKAGES
+# ggplot2
+# gridExtra
+# lemon (in case of use in the add argument)
+# scales
+# if raster plots are drawn (see the raster and raster.threshold arguments):
+# Cairo
+# grid
+# REQUIRED FUNCTIONS FROM THE cute PACKAGE
+# fun_gg_empty_graph()
+# fun_gg_palette()
+# fun_gg_point_rast()
+# fun_pack()
+# fun_check()
+# fun_round()
+# fun_scale()
+# fun_inter_ticks()
+# EXAMPLES
+# set.seed(1) ; obs1 <- data.frame(Km = c(2, 1, 6, 5, 4, 7), Time = c(2, 1, 6, 5, 4, 7)^2, Car = c("TUUT", "TUUT", "TUUT", "WIIM", "WIIM", "WIIM"), Color1 = rep(c("coral", "lightblue"), each = 3), stringsAsFactors = TRUE) ; fun_gg_scatter(data1 = obs1, x = "Km", y = "Time")
+# DEBUGGING
+# set.seed(1) ; obs1 <- data.frame(km = rnorm(1000, 10, 3), time = rnorm(1000, 10, 3), group1 = rep(c("A1", "A2"), 500), stringsAsFactors = TRUE) ; obs2 <-data.frame(km = rnorm(1000, 15, 3), time = rnorm(1000, 15, 3), group2 = rep(c("G1", "G2"), 500), stringsAsFactors = TRUE) ; set.seed(NULL) ; obs1$km[2:3] <- NA ; data1 = list(L1 = obs1, L2 = obs2) ; x = list(L1 = "km", L2 = "km") ; y = list(L1 = "time", L2 = "time") ; categ = list(L1 = "group1", L2 = "group2") ; categ = NULL ; categ.class.order = NULL ; color = NULL ; geom = "geom_point" ; geom.step.dir = "hv" ; geom.stick.base = NULL ; alpha = 0.5 ; dot.size = 2 ; dot.shape = 21 ; dot.border.size = 0.5 ; dot.border.color = NULL ; line.size = 0.5 ; line.type = "solid" ; x.lim = NULL ; x.lab = NULL ; x.log = "no" ; x.tick.nb = NULL ; x.second.tick.nb = NULL ; x.include.zero = FALSE ; x.left.extra.margin = 0.05 ; x.right.extra.margin = 0.05 ; x.text.angle = 0 ; y.lim = NULL ; y.lab = NULL ; y.log = "no" ; y.tick.nb = NULL ; y.second.tick.nb = NULL ; y.include.zero = FALSE ; y.top.extra.margin = 0.05 ; y.bottom.extra.margin = 0.05 ; y.text.angle = 0 ; raster = FALSE ; raster.ratio = 1 ; raster.threshold = NULL ; text.size = 12 ; title = "" ; title.text.size = 12 ; legend.show = TRUE ; legend.width = 0.5 ; legend.name = NULL ; article = TRUE ; grid = FALSE ; add = NULL ; return = FALSE ; return.ggplot = FALSE ; return.gtable = TRUE ; plot = TRUE ; warn.print = FALSE ; lib.path = NULL
+# function name
+function.name <- paste0(as.list(match.call(expand.dots=FALSE))[[1]], "()")
+arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
+arg.user.setting <- as.list(match.call(expand.dots=FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
+# end function name
+# required function checking
+req.function <- c(
+"fun_check", 
+"fun_gg_just", 
+"fun_gg_empty_graph", 
+"fun_gg_palette", 
+"fun_gg_point_rast", 
+"fun_round", 
+"fun_pack", 
+"fun_scale", 
+"fun_inter_ticks"
+)
+tempo <- NULL
+for(i1 in req.function){
+if(length(find(i1, mode = "function"))== 0L){
+tempo <- c(tempo, i1)
+}
+}
+if( ! is.null(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end required function checking
+# reserved words to avoid bugs (used in this function)
+reserved.words <- c("fake_x", "fake_y", "fake_categ")
+# end reserved words to avoid bugs (used in this function)
+# arg with no default values
+mandat.args <- c(
+"data1", 
+"x", 
+"y"
+)
+tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), ")")))
+if(any(tempo)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", "HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end arg with no default values
+# argument primary checking
+arg.check <- NULL #
+text.check <- NULL #
+checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
+ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
+tempo1 <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = data1, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OR A LIST OF DATA FRAMES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(x)){
+tempo1 <- fun_check(data = x, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = x, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(y)){
+tempo1 <- fun_check(data = y, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = y, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(categ)){
+tempo1 <- fun_check(data = categ, class = "vector", mode = "character", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = categ, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = categ, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(categ.class.order)){
+if(is.null(categ)){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT IS NOT NULL, BUT categ IS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = categ.class.order, class = "vector", mode = "character", fun.name = function.name)
+tempo2 <- fun_check(data = categ.class.order, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT MUST BE A VECTOR OF CHARACTER STRINGS OR A LIST OF VECTOR OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = categ.class.order, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(legend.name)){
+tempo1 <- fun_check(data = legend.name, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = legend.name, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = legend.name, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(color)){
+tempo1 <- fun_check(data = color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = color, class = "factor", na.contain = TRUE, fun.name = function.name)
+tempo3 <- fun_check(data = color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)
+tempo4 <- fun_check(data = color, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo4$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE & tempo3$problem == TRUE & tempo4$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT MUST BE A VECTOR (OF CHARACTER STRINGS OR INTEGERS) OR A FACTOR OR A LIST OF THESE POSSIBILITIES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = color, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo1 <- fun_check(data = geom, class = "vector", mode = "character", na.contain = FALSE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = geom, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = geom.step.dir, options = c("vh", "hv", "mid"), na.contain = FALSE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = geom.step.dir, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT MUST BE A SINGLE CHARACTER STRING (\"vh\" OR \"hv\" OR \"mid\") OR A LIST OF THESE CHARACTER STRINGS")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(geom.stick.base)){
+tempo1 <- fun_check(data = geom.stick.base, class = "vector", mode = "numeric", na.contain = FALSE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = color, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = geom.stick.base, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo1 <- fun_check(data = alpha, prop = TRUE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = alpha, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT MUST BE A SINGLE NUMERIC VALUE BETWEEN 0 AND 1 OR A LIST OF SUCH VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = dot.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
+tempo2 <- fun_check(data = dot.size, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = dot.shape, class = "vector", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = dot.shape, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT MUST BE A SINGLE SHAPE VALUE OR A LIST OF SINGLE SHAPE VALUES (SEE https://ggplot2.tidyverse.org/articles/ggplot2-specs.html)")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = dot.border.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
+tempo2 <- fun_check(data = dot.border.size, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(dot.border.color)){
+tempo1 <- fun_check(data = dot.border.color, class = "vector", mode = "character", length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+# integer colors -> gg_palette
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color MUST BE A SINGLE CHARACTER STRING OF COLOR OR A SINGLE INTEGER VALUE")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = dot.border.color, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo1 <- fun_check(data = line.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
+tempo2 <- fun_check(data = line.size, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo2$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+tempo1 <- fun_check(data = line.type, class = "vector", typeof = "integer", double.as.integer.allowed = FALSE, length = 1, fun.name = function.name)
+tempo2 <- fun_check(data = line.type, class = "vector", mode = "character", length = 1, fun.name = function.name)
+tempo3 <- fun_check(data = line.type, class = "list", na.contain = TRUE, fun.name = function.name)
+checked.arg.names <- c(checked.arg.names, tempo3$object.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE & tempo3$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT MUST BE A SINGLE LINE KIND VALUE OR A LIST OF SINGLE LINE KIND VALUES (SEE https://ggplot2.tidyverse.org/articles/ggplot2-specs.html)")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+if( ! is.null(x.lim)){
+tempo <- fun_check(data = x.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & any(x.lim %in% c(Inf, -Inf))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x.lim, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(x.lab)){
+if(all(class(x.lab) %in% "expression")){ # to deal with math symbols
+tempo <- fun_check(data = x.lab, class = "expression", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+tempo <- fun_check(data = x.lab, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x.lab, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = x.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(x.tick.nb)){
+tempo <- fun_check(data = x.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & x.tick.nb < 0){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(x.second.tick.nb)){
+tempo <- fun_check(data = x.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & x.second.tick.nb <= 0){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x.second.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = x.second.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = x.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.left.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.right.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = x.text.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+if( ! is.null(y.lim)){
+tempo <- fun_check(data = y.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & any(y.lim %in% c(Inf, -Inf))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.lim, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(y.lab)){
+if(all(class(y.lab) %in% "expression")){ # to deal with math symbols
+tempo <- fun_check(data = y.lab, class = "expression", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+tempo <- fun_check(data = y.lab, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.lab, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = y.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(y.tick.nb)){
+tempo <- fun_check(data = y.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & y.tick.nb < 0){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if( ! is.null(y.second.tick.nb)){
+tempo <- fun_check(data = y.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE & y.second.tick.nb <= 0){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y.second.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = y.second.tick.nb, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = y.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.top.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.bottom.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = y.text.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = raster, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = raster.ratio, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+if( ! is.null(raster.threshold)){
+tempo <- fun_check(data = raster.threshold, class = "vector", typeof = "integer", neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = raster.threshold, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = legend.show, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(legend.width)){
+tempo <- fun_check(data = legend.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = legend.width, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = article, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = grid, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(add)){
+tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = add, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.ggplot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = return.gtable, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
+if( ! is.null(lib.path)){
+tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
+if(tempo$problem == FALSE){
+if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
+tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
+text.check <- c(text.check, tempo.cat)
+arg.check <- c(arg.check, TRUE)
+}
+}
+}else{
+# no fun_check test here, it is just for checked.arg.names
+tempo <- fun_check(data = lib.path, class = "vector")
+checked.arg.names <- c(checked.arg.names, tempo$object.name)
+}
+if(any(arg.check) == TRUE){
+stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
+}
+# source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
+# end argument primary checking
+
+
+# second round of checking and data preparation
+# management of NA arguments
+tempo.arg <- names(arg.user.setting) # values provided by the user
+tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length)== 1L # no argument provided by the user can be just NA
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NA arguments
+# management of NULL arguments
+tempo.arg <-c(
+"data1", 
+# "x", # inactivated because of hline or vline
+# "y", # inactivated because of hline or vline
+"geom", 
+"geom.step.dir", 
+# "geom.stick.base", # inactivated because can be null
+"alpha", 
+"dot.size", 
+"dot.shape", 
+"dot.border.size", 
+"line.size", 
+"line.type", 
+"x.log", 
+"x.include.zero", 
+"x.left.extra.margin", 
+"x.right.extra.margin", 
+"x.text.angle", 
+"y.log", 
+"y.include.zero", 
+"y.top.extra.margin", 
+"y.bottom.extra.margin", 
+"y.text.angle", 
+"raster", 
+"raster.ratio", 
+"text.size", 
+"title", 
+"title.text.size", 
+"legend.show", 
+# "legend.width", # inactivated because can be null
+"article", 
+"grid", 
+"return", 
+"return.ggplot", 
+"return.gtable", 
+"plot", 
+"warn.print"
+)
+tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
+if(any(tempo.log) == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
+}
+# end management of NULL arguments
+# code that protects set.seed() in the global environment
+# end code that protects set.seed() in the global environment
+# warning initiation
+ini.warning.length <- options()$warning.length
+options(warning.length = 8170)
+warn <- NULL
+warn.count <- 0
+# end warning initiation
+# other checkings
+# check list lengths (and names of data1 compartments if present)
+list.color <- NULL
+list.geom <- NULL
+list.geom.step.dir <- NULL
+list.geom.stick.base <- NULL
+list.alpha <- NULL
+list.dot.size <- NULL
+list.dot.shape <- NULL
+list.dot.border.size <- NULL
+list.dot.border.color <- NULL
+list.line.size <- NULL
+list.line.type <- NULL
+if(all(class(data1) == "list")){
+if(length(data1) > 6){
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A LIST OF 6 DATA FRAMES MAXIMUM (6 OVERLAYS MAX)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(is.null(names(data1))){
+names(data1) <- paste0("L", 1:length(data1))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL NAME COMPARTMENT OF data1 LIST -> NAMES RESPECTIVELY ATTRIBUTED TO EACH COMPARTMENT:\n", paste(names(data1), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+if( ! is.null(x)){
+if( ! (all(class(x) == "list") & length(data1) == length(x))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}else{
+x <- vector("list", length(data1))
+}
+if( ! is.null(y)){
+if( ! (all(class(y) == "list") & length(data1) == length(y))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}else{
+y <- vector("list", length(data1))
+}
+if( ! is.null(categ)){
+if( ! (all(class(categ) == "list") & length(data1) == length(categ))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if( ! is.null(categ.class.order)){
+if( ! (all(class(categ.class.order) == "list") & length(data1) == length(categ.class.order))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if( ! is.null(color)){
+if( ! ((all(class(color) == "list") & length(data1) == length(color)) | ((all(mode(color) == "character") | all(mode(color) == "numeric")) & length(color)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER STRING OR INTEGER")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if((all(mode(color) == "character") | all(mode(color) == "numeric")) & length(color)== 1L){ # convert the single value into a list of single value
+list.color <- vector(mode = "list", length = length(data1))
+list.color[] <- color
+}
+}
+if( ! ((all(class(geom) == "list") & length(data1) == length(geom)) | (all(mode(geom) == "character") & length(geom)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(geom) == "character") & length(geom)== 1L){ # convert the single value into a list of single value
+list.geom <- vector(mode = "list", length = length(data1))
+list.geom[] <- geom
+}
+if( ! ((all(class(geom.step.dir) == "list") & length(data1) == length(geom.step.dir)) | (all(mode(geom.step.dir) == "character") & length(geom.step.dir)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(geom.step.dir) == "character") & length(geom.step.dir)== 1L){ # convert the single value into a list of single value
+list.geom.step.dir <- vector(mode = "list", length = length(data1))
+list.geom.step.dir[] <- geom.step.dir
+}
+if( ! is.null(geom.stick.base)){
+if( ! ((all(class(geom.stick.base) == "list") & length(data1) == length(geom.stick.base)) | (all(mode(geom.stick.base) == "numeric") & length(geom.stick.base)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(geom.stick.base) == "numeric") & length(geom.stick.base)== 1L){ # convert the single value into a list of single value
+list.geom.stick.base <- vector(mode = "list", length = length(data1))
+list.geom.stick.base[] <- geom.stick.base
+}
+}
+if( ! ((all(class(alpha) == "list") & length(data1) == length(alpha)) | (all(mode(alpha) == "numeric") & length(alpha)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(alpha) == "numeric") & length(alpha)== 1L){ # convert the single value into a list of single value
+list.alpha <- vector(mode = "list", length = length(data1))
+list.alpha[] <- alpha
+}
+if( ! ((all(class(dot.size) == "list") & length(data1) == length(dot.size)) | (all(mode(dot.size) == "numeric") & length(dot.size)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(dot.size) == "numeric") & length(dot.size)== 1L){ # convert the single value into a list of single value
+list.dot.size <- vector(mode = "list", length = length(data1))
+list.dot.size[] <- dot.size
+}
+if( ! ((all(class(dot.shape) == "list") & length(data1) == length(dot.shape)) | (all(mode(dot.shape) != "list") & length(dot.shape)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE SHAPE VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(dot.shape) != "list") & length(dot.shape)== 1L){ # convert the single value into a list of single value
+list.dot.shape <- vector(mode = "list", length = length(data1))
+list.dot.shape[] <- dot.shape
+}
+if( ! ((all(class(dot.border.size) == "list") & length(data1) == length(dot.border.size)) | (all(mode(dot.border.size) == "numeric") & length(dot.border.size)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(dot.border.size) == "numeric") & length(dot.border.size)== 1L){ # convert the single value into a list of single value
+list.dot.border.size <- vector(mode = "list", length = length(data1))
+list.dot.border.size[] <- dot.border.size
+}
+if( ! is.null(dot.border.color)){
+if( ! ((all(class(dot.border.color) == "list") & length(data1) == length(dot.border.color)) | ((all(mode(dot.border.color) == "character") | all(mode(dot.border.color) == "numeric")) & length(dot.border.color)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER STRING OR INTEGER")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if((all(mode(dot.border.color) == "character") | all(mode(dot.border.color) == "numeric")) & length(dot.border.color)== 1L){ # convert the single value into a list of single value
+list.dot.border.color <- vector(mode = "list", length = length(data1))
+list.dot.border.color[] <- dot.border.color
+}
+}
+if( ! ((all(class(line.size) == "list") & length(data1) == length(line.size)) | (all(mode(line.size) == "numeric") & length(line.size)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(line.size) == "numeric") & length(line.size)== 1L){ # convert the single value into a list of single value
+list.line.size <- vector(mode = "list", length = length(data1))
+list.line.size[] <- line.size
+}
+if( ! ((all(class(line.type) == "list") & length(data1) == length(line.type)) | (all(mode(line.type) != "list") & length(line.type)== 1L))){ # list of same length as data1 or single value
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE LINE KIND VALUE")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(all(mode(line.type) != "list") & length(line.type)== 1L){ # convert the single value into a list of single value
+list.line.type <- vector(mode = "list", length = length(data1))
+list.line.type[] <- line.type
+}
+if( ! is.null(legend.name)){
+if( ! (all(class(legend.name) == "list") & length(data1) == length(legend.name))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+}
+# end check list lengths (and names of data1 compartments if present)
+# conversion into lists
+if(all(is.data.frame(data1))){
+data1 <- list(L1 = data1)
+if(all(class(x) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+x <- list(L1 = x)
+}
+if(all(class(y) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+y <- list(L1 = y)
+}
+if( ! is.null(categ)){
+if(all(class(categ) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+categ <- list(L1 = categ)
+}
+}
+if( ! is.null(categ.class.order)){
+if(all(class(categ.class.order) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+categ.class.order <- list(L1 = categ.class.order)
+}
+}
+if( ! is.null(color)){
+if(all(class(color) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+color <- list(L1 = color)
+}
+}
+if(all(class(geom) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+geom <- list(L1 = geom)
+}
+if(all(class(geom.step.dir) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+geom.step.dir <- list(L1 = geom.step.dir)
+}
+if( ! is.null(geom.stick.base)){
+if(all(class(geom.stick.base) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+geom.stick.base <- list(L1 = geom.stick.base)
+}
+}
+if(all(class(alpha) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+alpha <- list(L1 = alpha)
+}
+if(all(class(dot.size) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+dot.size <- list(L1 = dot.size)
+}
+if(all(class(dot.shape) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+dot.shape <- list(L1 = dot.shape)
+}
+if(all(class(dot.border.size) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+dot.border.size <- list(L1 = dot.border.size)
+}
+if( ! is.null(dot.border.color)){
+if(all(class(dot.border.color) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+dot.border.color <- list(L1 = dot.border.color)
+}
+}
+if(all(class(line.size) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+line.size <- list(L1 = line.size)
+}
+if(all(class(line.type) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+line.type <- list(L1 = line.type)
+}
+if( ! is.null(legend.name)){
+if(all(class(legend.name) == "list")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+legend.name <- list(L1 = legend.name)
+}
+}
+}else if( ! all(sapply(data1, FUN = "class") == "data.frame")){ # if not a data frame, data1 can only be a list, as tested above
+tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OR A LIST OF DATA FRAMES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+# single value converted into list now reattributed to the argument name
+if( ! is.null(color)){
+if( ! is.null(list.color)){
+color <- list.color
+}
+}
+if( ! is.null(list.geom)){
+geom <- list.geom
+}
+if( ! is.null(list.geom.step.dir)){
+geom.step.dir <- list.geom.step.dir
+}
+if( ! is.null(geom.stick.base)){
+if( ! is.null(list.geom.stick.base)){
+geom.stick.base <- list.geom.stick.base
+}
+}
+if( ! is.null(list.alpha)){
+alpha <- list.alpha
+}
+if( ! is.null(list.dot.size)){
+dot.size <- list.dot.size
+}
+if( ! is.null(list.dot.shape)){
+dot.shape <- list.dot.shape
+}
+if( ! is.null(list.dot.border.size)){
+dot.border.size <- list.dot.border.size
+}
+if( ! is.null(dot.border.color)){
+if( ! is.null(list.dot.border.color)){
+dot.border.color <- list.dot.border.color
+}
+}
+if( ! is.null(list.line.size)){
+line.size <- list.line.size
+}
+if( ! is.null(list.line.type)){
+line.type <- list.line.type
+}
+# end single value converted into list now reattributed to the argument name
+# data, x, y, geom, alpha, dot.size, shape, dot.border.size, line.size, line.type, legend.name are list now
+# if non-null, categ, categ.class.order, legend.name, color, dot.border.color are list now
+# end conversion into lists
+# verif of add
+if( ! is.null(add)){
+if( ! grepl(pattern = "^\\s*\\+", add)){ # check that the add string start by +
+tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+
+}else if( ! grepl(pattern = "(ggplot2|lemon)\\s*::", add)){ #
+tempo.cat <- paste0("ERROR IN ", function.name, ": FOR EASIER FUNCTION DETECTION, add ARGUMENT MUST CONTAIN \"ggplot2::\" OR \"lemon::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if( ! grepl(pattern = ")\\s*$", add)){ # check that the add string finished by )
+tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+# end verif of add
+# management of add containing facet
+facet.categ <- NULL
+if( ! is.null(add)){
+facet.check <- TRUE
+tempo <- unlist(strsplit(x = add, split = "\\s*\\+\\s*(ggplot2|lemon)\\s*::\\s*")) #
+tempo <- sub(x = tempo, pattern = "^facet_wrap", replacement = "ggplot2::facet_wrap")
+tempo <- sub(x = tempo, pattern = "^facet_grid", replacement = "ggplot2::facet_grid")
+tempo <- sub(x = tempo, pattern = "^facet_rep", replacement = "lemon::facet_rep")
+if(length(data1) > 1 & (any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")) | grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid"))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nfacet PANELS CANNOT BE USED IF MORE THAN ONE DATA FRAME IN THE data1 ARGUMENT\nPLEASE REWRITE THE add STRING AND RERUN")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+if(any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap"))){
+tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")])))
+facet.categ <- list(names(tempo1$params$facets)) # list of length 1
+tempo.text <- "facet_wrap OR facet_rep_wrap"
+facet.check <- FALSE
+}else if(grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")){
+tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")])))
+facet.categ <- list(c(names(tempo1$params$rows), names(tempo1$params$cols))) # list of length 1
+tempo.text <- "facet_grid OR facet_rep_grid"
+facet.check <- FALSE
+}
+if(facet.check == FALSE & ! all(facet.categ %in% names(data1[[1]]))){ # WARNING: all(facet.categ %in% names(data1)) is TRUE when facet.categ is NULL
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF \"", tempo.text, "\" STRING IN THE add ARGUMENT BUT PROBLEM OF VARIABLE DETECTION (COLUMN NAMES OF data1)\nTHE DETECTED VARIABLES ARE:\n", paste(facet.categ, collapse = " "), "\nTHE data1 COLUMN NAMES ARE:\n", paste(names(data1[[1]]), collapse = " "), "\nPLEASE REWRITE THE add STRING AND RERUN")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+}
+# if facet.categ is not NULL, it is a list of length 1 now
+# end management of add containing facet
+# legend name filling
+if(is.null(legend.name) & ! is.null(categ)){
+legend.name <- categ
+}else if(is.null(legend.name) & is.null(categ)){
+legend.name <- vector("list", length(data1)) # null list
+}
+# legend.name not NULL anymore (list)
+# end legend name filling
+# ini categ for legend display
+fin.lg.disp <- vector("list", 6) # will be used at the end to display or not legends
+fin.lg.disp[] <- FALSE
+legend.disp <- vector("list", length(data1))
+if(is.null(categ) | legend.show == FALSE){
+legend.disp[] <- FALSE
+}else{
+for(i2 in 1:length(data1)){
+if(is.null(categ[[i2]])){
+legend.disp[[i2]] <- FALSE
+}else{
+legend.disp[[i2]] <- TRUE
+}
+}
+}
+# end ini categ for legend display
+# integer colors into gg_palette
+tempo.check.color <- NULL
+for(i1 in 1:length(data1)){
+if(any(is.na(color[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), ": color ARGUMENT CANNOT CONTAIN NA")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo.check.color <- c(tempo.check.color, fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem)
+}
+tempo.check.color <- ! tempo.check.color # invert TRUE and FALSE because if integer, then problem = FALSE
+if(any(tempo.check.color == TRUE)){ # convert integers into colors
+tempo.integer <- unlist(color[tempo.check.color])
+tempo.color <- fun_gg_palette(max(tempo.integer, na.rm = TRUE))
+for(i1 in 1:length(data1)){
+if(tempo.check.color[i1] == TRUE){
+color[[i1]] <-tempo.color[color[[i1]]]
+}
+}
+}
+# end integer colors into gg_palette
+# loop (checking inside list compartment)
+compart.null.color <- 0 # will be used to attribute a color when color is non-null but a compartment of color is NULL
+data1.ini <- data1 # to report NA removal
+removed.row.nb <- vector("list", length = length(data1)) # to report NA removal. Contains NULL
+removed.rows <- vector("list", length = length(data1)) # to report NA removal. Contains NULL
+for(i1 in 1:length(data1)){
+tempo <- fun_check(data = data1[[i1]], data.name = ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "data.frame", na.contain = TRUE, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+# reserved word checking
+if(any(names(data1[[i1]]) %in% reserved.words)){ # I do not use fun_name_change() because cannot control y before creating "fake_y". But ok because reserved are not that common
+tempo.cat <- paste0("ERROR IN ", function.name, ": COLUMN NAMES OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " ARGUMENT CANNOT BE ONE OF THESE WORDS\n", paste(reserved.words, collapse = " "), "\nTHESE ARE RESERVED FOR THE ", function.name, " FUNCTION")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if( ! (is.null(add))){
+if(any(sapply(X = reserved.words, FUN = grepl, x = add))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF COLUMN NAMES OF data1 IN THE add ARGUMENT STRING, THAT CORRESPOND TO RESERVED STRINGS FOR ", function.name, "\nFOLLOWING COLUMN NAMES HAVE TO BE CHANGED:\n", paste(arg.names[sapply(X = reserved.words, FUN = grepl, x = add)], collapse = "\n"), "\nFOR INFORMATION, THE RESERVED WORDS ARE:\n", paste(reserved.words, collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(any(sapply(X = arg.names, FUN = grepl, x = add))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NAMES OF ", function.name, " ARGUMENTS DETECTED IN THE add STRING:\n", paste(arg.names[sapply(X = arg.names, FUN = grepl, x = add)], collapse = "\n"), "\nRISK OF WRONG OBJECT USAGE INSIDE ", function.name)
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end reserved word checking
+# check of geom now because required for y argument
+tempo <- fun_check(data = geom[[i1]], data.name = ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), options = c("geom_point", "geom_line", "geom_path", "geom_step", "geom_hline", "geom_vline", "geom_stick"), length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(geom[[i1]] == "geom_step" & is.null(geom.step.dir[[i1]])){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(geom.step.dir)== 1L, "geom.step.dir", paste0("ELEMENT ", i1, " OF geom.step.dir ARGUMENT")), ": geom.step.dir ARGUMENT CANNOT BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("ELEMENT ", i1, " OF geom")), " ARGUMENT IS \"geom_step\"\nHERE geom.step.dir ARGUMENT IS: ", paste(geom.step.dir[[i1]], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(geom[[i1]] == "geom_step" & ! is.null(geom.step.dir[[i1]])){
+tempo <- fun_check(data = geom.step.dir[[i1]], data.name = ifelse(length(geom.step.dir)== 1L, "geom.step.dir", paste0("geom.step.dir NUMBER ", i1)), options = c("vh", "hv", "mid"), length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if( ! (is.null(geom.stick.base))){
+if(geom[[i1]] == "geom_stick" & ! is.null(geom.stick.base[[i1]])){
+tempo <- fun_check(data = geom.stick.base[[i1]], data.name = ifelse(length(geom.stick.base)== 1L, "geom.stick.base", paste0("geom.stick.base NUMBER ", i1)), mode = "numeric", length = 1, na.contain = FALSE, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+}
+# end check of geom now because required for y argument
+if(is.null(x[[i1]])){
+if(all(geom[[i1]] != "geom_hline")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": x ARGUMENT CANNOT BE NULL EXCEPT IF ", ifelse(length(geom)== 1L, "x", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_hline\"\nHERE geom ARGUMENT IS: ", paste(geom[[i1]], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+x[[i1]] <- "fake_x"
+data1[[i1]] <- cbind(data1[[i1]], fake_x = NA, stringsAsFactors = TRUE)
+data1[[i1]][, "fake_x"] <- as.numeric(data1[[i1]][, "fake_x"])
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT ASSOCIATED TO ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT ", geom[[i1]], " -> FAKE COLUMN ADDED TO DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", NAMED \"fake_x\" FOR FINAL DRAWING")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(all(geom[[i1]] == "geom_hline")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": x ARGUMENT MUST BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_hline\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo <- fun_check(data = x[[i1]], data.name = ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), class = "vector", mode = "character", length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(is.null(y[[i1]])){
+if(all(geom[[i1]] != "geom_vline")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": y ARGUMENT CANNOT BE NULL EXCEPT IF ", ifelse(length(geom)== 1L, "y", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_vline\"\nHERE geom ARGUMENT IS: ", paste(geom[[i1]], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+y[[i1]] <- "fake_y"
+data1[[i1]] <- cbind(data1[[i1]], fake_y = NA, stringsAsFactors = TRUE)
+data1[[i1]][, "fake_y"] <- as.numeric(data1[[i1]][, "fake_y"])
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT ASSOCIATED TO ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT ", geom[[i1]], " -> FAKE COLUMN ADDED TO DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", NAMED \"fake_y\" FOR FINAL DRAWING")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else{
+if(all(geom[[i1]] == "geom_vline")){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": y ARGUMENT MUST BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_vline\"")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo <- fun_check(data = y[[i1]], data.name = ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), class = "vector", mode = "character", length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+# x[[i1]] and y[[i1]] not NULL anymore
+if( ! (x[[i1]] %in% names(data1[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(x[[i1]], collapse = " "))))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if( ! (y[[i1]] %in% names(data1[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(y[[i1]], collapse = " "))))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo <- fun_check(data = data1[[i1]][, x[[i1]]], data.name = ifelse(length(x)== 1L, "x ARGUMENT (AS COLUMN NAME OF data1 DATA FRAME)", paste0("ELEMENT ", i1, " OF x ARGUMENT", " (AS COLUMN NAME OF data1 DATA FRAME NUMBER ", i1, ")")), class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo <- fun_check(data = data1[[i1]][, y[[i1]]], data.name = ifelse(length(y)== 1L, "y ARGUMENT (AS COLUMN NAME OF data1 DATA FRAME)", paste0("ELEMENT ", i1, " OF y ARGUMENT", " (AS COLUMN NAME OF data1 DATA FRAME NUMBER ", i1, ")")), class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(x[[i1]] == "fake_x" & y[[i1]] == "fake_y"){ # because the code cannot accept to be both "fake_x" and "fake_y" at the same time
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2\nTHE CODE CANNOT ACCEPT x AND y TO BE \"fake_x\" AND \"fake_y\" IN THE SAME DATA FRAME ", i1, " ")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+
+if(( ! is.null(categ)) & ( ! is.null(categ[[i1]]))){ # is.null(categ[[i1]]) works even if categ is NULL # is.null(categ[[i1]]) works even if categ is NULL # if categ[[i1]] = NULL, fake_categ will be created later on
+tempo <- fun_check(data = categ[[i1]], data.name = ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")),, class = "vector", mode = "character", length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if( ! (categ[[i1]] %in% names(data1[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(categ[[i1]], collapse = " "))))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+tempo1 <- fun_check(data = data1[[i1]][, categ[[i1]]], data.name = ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
+tempo2 <- fun_check(data = data1[[i1]][, categ[[i1]]], data.name = ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "factor", na.contain = TRUE, fun.name = function.name)
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " MUST BE A FACTOR OR CHARACTER VECTOR")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(tempo1$problem == FALSE){
+data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE CHARACTER COLUMN HAS BEEN CONVERTED TO FACTOR")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+
+}
+if(geom[[i1]] == "geom_vline" | geom[[i1]] == "geom_hline"){
+if(length(unique(data1[[i1]][, categ[[i1]]])) != nrow(data1[[i1]])){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(geom)== 1L, "geom OF data1 ARGUMENT", paste0("geom NUMBER ", i1, " OF DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " ARGUMENT IS ", geom[[i1]], ", MEANING THAT ", ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " MUST HAVE A DIFFERENT CLASS PER LINE OF data1 (ONE x VALUE PER CLASS)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+}else if(( ! is.null(categ)) & is.null(categ[[i1]])){ # is.null(categ[[i1]]) works even if categ is NULL # if categ[[i1]] = NULL, fake_categ will be created. WARNING: is.null(categ[[i1]]) means no legend display (see above), because categ has not been precised. This also means a single color for data1[[i1]]
+if(length(color[[i1]]) > 1){ # 0 means is.null(color[[i1]]) or is.null(color) and 1 is ok -> single color for data1[[i1]]
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT BUT CORRESPONDING COLORS IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " HAS LENGTH OVER 1\n", paste(color[[i1]], collapse = " "), "\nWHICH IS NOT COMPATIBLE WITH NULL CATEG -> COLOR RESET TO A SINGLE COLOR")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+color[i1] <- list(NULL) # will provide a single color below # Warning color[[i1]] <- NULL removes the compartment
+}
+categ[[i1]] <- "fake_categ"
+data1[[i1]] <- cbind(data1[[i1]], fake_categ = "", stringsAsFactors = TRUE)
+# inactivated because give a different color to different "Line_" categ while a single color for all the data1[[i1]] required. Thus, put back after the color management
+# if(geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline"){
+# data1[[i1]][, "fake_categ"] <- paste0("Line_", 1:nrow(data1[[i1]]))
+# }else{
+data1[[i1]][, "fake_categ"] <- data1[[i1]][, "fake_categ"] # as.numeric("") create a vector of NA but class numeric
+# }
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT -> FOR DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT:", paste0("NUMBER ", i1, " OF data1 ARGUMENT:")), "\n- FAKE \"fake_categ\" COLUMN ADDED FILLED WITH \"\"(OR WITH \"Line_...\" FOR LINES)\n- SINGLE COLOR USED FOR PLOTTING\n- NO LEGEND DISPLAYED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# OK: if categ is not NULL, all the non-null categ columns of data1 are factors from here
+
+# management of log scale and Inf removal
+if(x[[i1]] != "fake_x"){
+if(any(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN ", ifelse(length(categ)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(y[[i1]] != "fake_y"){
+if(any(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN ", ifelse(length(categ)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# log conversion
+if(x.log != "no"){
+tempo1 <- ! is.finite(data1[[i1]][, x[[i1]]]) # where are initial NA and Inf
+data1[[i1]][, x[[i1]]] <- suppressWarnings(get(x.log)(data1[[i1]][, x[[i1]]]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+if(any( ! (tempo1 | is.finite(data1[[i1]][, x[[i1]]])))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN ", ifelse(length(categ)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(y.log != "no"){
+tempo1 <- ! is.finite(data1[[i1]][, y[[i1]]]) # where are initial NA and Inf
+data1[[i1]][, y[[i1]]] <- suppressWarnings(get(y.log)(data1[[i1]][, y[[i1]]]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+if(any( ! (tempo1 | is.finite(data1[[i1]][, y[[i1]]])))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN ", ifelse(length(categ)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# Inf removal
+# removed.row.nb[[i1]] <- NULL # already NULL and Warning this removes the compartment
+removed.rows[[i1]] <- data.frame(stringsAsFactors = FALSE)
+if(any(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])) detects only Inf
+removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], which(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]]))))
+}
+if(any(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])) detects only Inf
+removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], which(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]]))))
+}
+if( ! is.null(removed.row.nb[[i1]])){
+removed.row.nb[[i1]] <- unique(removed.row.nb[[i1]]) # to remove the duplicated positions (NA in both x and y)
+removed.rows[[i1]] <- rbind(removed.rows[[i1]], data1.ini[[i1]][removed.row.nb[[i1]], ]) # here data1.ini used to have the y = O rows that will be removed because of Inf creation after log transformation
+data1[[i1]] <- data1[[i1]][-removed.row.nb[[i1]], ]
+data1.ini[[i1]] <- data1.ini[[i1]][-removed.row.nb[[i1]], ] #
+}
+# From here, data1 and data.ini have no more Inf
+# end Inf removal
+# x.lim and y.lim dealt later on, after the end f the loop
+# end management of log scale and Inf removal
+# management of log scale
+if(x.log != "no"){
+data1[[i1]][, x[[i1]]] <- suppressWarnings(get(x.log)(data1[[i1]][, x[[i1]]])) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+if(y.log != "no"){
+data1[[i1]][, y[[i1]]] <- suppressWarnings(get(y.log)(data1[[i1]][, y[[i1]]])) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+# end management of log scale
+# na detection and removal
+column.check <- unique(unlist(c( # unlist because creates a list
+if(x[[i1]] == "fake_x"){NULL}else{x[[i1]]}, 
+if(y[[i1]] == "fake_y"){NULL}else{y[[i1]]}, 
+if( ! is.null(categ)){if(is.null(categ[[i1]])){NULL}else{categ[[i1]]}}, 
+if( ! is.null(facet.categ)){if(is.null(facet.categ[[i1]])){NULL}else{facet.categ[[i1]]}}
+))) # dot.categ because can be a 3rd column of data1
+if(any(is.na(data1[[i1]][, column.check]))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS ", paste(column.check, collapse = " "), " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+for(i3 in 1:length(column.check)){
+if(any(is.na(data1[[i1]][, column.check[i3]]))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i3], " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+tempo <- unique(unlist(lapply(lapply(c(data1[[i1]][column.check]), FUN = is.na), FUN = which)))
+removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], tempo)
+removed.rows[[i1]] <- rbind(removed.rows[[i1]], data1.ini[[i1]][tempo, ]) #  # tempo used because removed.row.nb is not empty. Here data1.ini used to have the non NA rows that will be removed because of NAN creation after log transformation (neg values for instance)
+column.check <- column.check[ ! (column.check == x[[i1]] | column.check == y[[i1]])] # remove x and y to keep quali columns
+if(length(tempo) != 0){
+data1[[i1]] <- data1[[i1]][-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
+data1.ini[[i1]] <- data1.ini[[i1]][-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers than the former
+for(i4 in 1:length(column.check)){
+if(any( ! unique(removed.rows[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]]))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i4], " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA REMOVAL\n(IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[[i1]][, column.check[i4]])[ ! unique(removed.rows[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]])], collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+tempo.levels <- levels(data1[[i1]][, column.check[i4]])[levels(data1[[i1]][, column.check[i4]]) %in% unique(as.character(data1[[i1]][, column.check[i4]]))]
+data1[[i1]][, column.check[i4]] <- factor(as.character(data1[[i1]][, column.check[i4]]), levels = tempo.levels)
+if(column.check[i4] %in% categ[[i1]] & ! is.null(categ.class.order)){
+categ.class.order[[i1]] <- levels(data1[[i1]][, column.check[i4]])[levels(data1[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]])] # remove the absent class in the categ.class.order vector
+data1[[i1]][, column.check[i4]] <- factor(as.character(data1[[i1]][, column.check[i4]]), levels = unique(categ.class.order[[i1]]))
+}
+}
+}
+}
+}
+# end na detection and removal
+# From here, data1 and data.ini have no more NA or NaN in x, y, categ (if categ != NULL) and facet.categ (if categ != NULL)
+if( ! is.null(categ.class.order)){
+# the following check will be done several times but I prefer to keep it here, after the creation of categ
+if(is.null(categ[[i1]]) & ! is.null(categ.class.order[[i1]])){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ ARGUMENT CANNOT BE NULL IF COMPARTMENT ", i1, " OF categ.class.order ARGUMENT IS NOT NULL: ", paste(categ.class.order, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+if(is.null(categ.class.order[[i1]])){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE categ.class.order COMPARTMENT ", i1, " IS NULL. ALPHABETICAL ORDER WILL BE APPLIED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+data1[[i1]][, categ[[i1]]] <- factor(as.character(data1[[i1]][, categ[[i1]]])) # if already a factor, change nothing, if characters, levels according to alphabetical order
+categ.class.order[[i1]] <- levels(data1[[i1]][, categ[[i1]]]) # character vector that will be used later
+}else{
+tempo <- fun_check(data = categ.class.order[[i1]], data.name = paste0("COMPARTMENT ", i1 , " OF categ.class.order ARGUMENT"), class = "vector", mode = "character", length = length(levels(data1[[i1]][, categ[[i1]]])), fun.name = function.name) # length(data1[, categ[i1]) -> if data1[, categ[i1] was initially character vector, then conversion as factor after the NA removal, thus class number ok. If data1[, categ[i1] was initially factor, no modification after the NA removal, thus class number ok
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(any(duplicated(categ.class.order[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(categ.class.order[[i1]], collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if( ! (all(categ.class.order[[i1]] %in% unique(data1[[i1]][, categ[[i1]]])) & all(unique(data1[[i1]][, categ[[i1]]]) %in% categ.class.order[[i1]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ.class.order ARGUMENT MUST BE CLASSES OF COMPARTMENT ", i1, " OF categ ARGUMENT\nHERE IT IS:\n", paste(categ.class.order[[i1]], collapse = " "), "\nFOR COMPARTMENT ", i1, " OF categ.class.order AND IT IS:\n", paste(unique(data1[[i1]][, categ[[i1]]]), collapse = " "), "\nFOR COLUMN ", categ[[i1]], " OF data1 NUMBER ", i1)
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]], levels = categ.class.order[[i1]]) # reorder the factor
+}
+names(categ.class.order)[i1] <- categ[[i1]]
+}
+}
+# OK: if categ.class.order is not NULL, all the NULL categ.class.order columns of data1 are character from here
+
+if( ! is.null(legend.name[[i1]])){
+tempo <- fun_check(data = legend.name[[i1]], data.name = ifelse(length(legend.name)== 1L, "legend.name", paste0("legend.name NUMBER ", i1)),, class = "vector", mode = "character", length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if( ! is.null(color)){ # if color is NULL, will be filled later on
+# check the nature of color
+if(is.null(color[[i1]])){
+compart.null.color <- compart.null.color + 1
+color[[i1]] <- grey(compart.null.color / 8) # cannot be more than 7 overlays. Thus 7 different greys. 8/8 is excluded because white dots
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL COLOR IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " ASSOCIATED TO ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", SINGLE COLOR ", paste(color[[i1]], collapse = " "), " HAS BEEN ATTRIBUTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+tempo1 <- fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name) # na.contain = TRUE in case of colum of data1
+tempo2 <- fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "factor", na.contain = TRUE, fun.name = function.name) # idem
+if(tempo1$problem == TRUE & tempo2$problem == TRUE){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A FACTOR OR CHARACTER VECTOR OR INTEGER VECTOR") # integer possible because dealt above
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if( ! (all(color[[i1]] %in% colors() | grepl(pattern = "^#", color[[i1]])))){ # check that all strings of low.color start by #
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors(): ", paste(unique(color[[i1]]), collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(any(is.na(color[[i1]]))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), ", THE COLORS:\n", paste(unique(color[[i1]]), collapse = " "), "\nCONTAINS NA")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+# end check the nature of color
+# check the length of color
+if(is.null(categ) & length(color[[i1]]) != 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A SINGLE COLOR IF categ IS NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if( ! is.null(categ)){
+# No problem of NA management by ggplot2 because already removed
+if(categ[[i1]] == "fake_categ" & length(color[[i1]]) != 1){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A SINGLE COLOR IF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IS NULL")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(length(color[[i1]]) == length(unique(data1[[i1]][, categ[[i1]]]))){ # here length(color) is equal to the different number of categ
+data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE FOLLOWING COLORS:\n", paste(color[[i1]], collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else if(length(color[[i1]]) == length(data1[[i1]][, categ[[i1]]])){# here length(color) is equal to nrow(data1[[i1]]) -> Modif to have length(color) equal to the different number of categ (length(color) == length(levels(data1[[i1]][, categ[[i1]]])))
+data1[[i1]] <- cbind(data1[[i1]], color = color[[i1]], stringsAsFactors = TRUE)
+tempo.check <- unique(data1[[i1]][ , c(categ[[i1]], "color")])
+if( ! (nrow(data1[[i1]]) == length(color[[i1]]) & nrow(tempo.check) == length(unique(data1[[i1]][ , categ[[i1]]])))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color")), " ARGUMENT HAS THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nBUT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF THIS categ:\n", paste(unique(mapply(FUN = "paste", data1[[i1]][ ,categ[[i1]]], data1[[i1]][ ,"color"])), collapse = "\n"))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+color[[i1]] <- unique(color[[i1]][order(data1[[i1]][, categ[[i1]]])]) # Modif to have length(color) equal to the different number of categ (length(color) == length(levels(data1[[i1]][, categ[[i1]]])))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count, ") FROM FUNCTION ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " HAS THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " COLUMN VALUES\nCOLORS HAVE BEEN RESPECTIVELY ASSOCIATED TO EACH CLASS OF categ AS:\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "), "\n", paste(color[[i1]], collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else if(length(color[[i1]])== 1L){
+data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
+color[[i1]] <- rep(color[[i1]], length(levels(data1[[i1]][, categ[[i1]]])))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", COLOR HAS LENGTH 1 MEANING THAT ALL THE DIFFERENT CLASSES OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), "\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(color[[i1]], collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE\n(1) LENGTH 1\nOR (2) THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " COLUMN VALUES\nOR (3) THE LENGTH OF THE CLASSES IN THIS COLUMN\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LENGTH ", length(data1[[i1]][, categ[[i1]]]), " AND CATEG CLASS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])), "\nPRESENCE OF NA IN THE COLUMN x, y OR categ OF data1 COULD BE THE PROBLEME")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+}
+if((geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline") & ! is.null(categ[[i1]])){ # add here after the color management, to deal with the different lines to plot inside any data[[i1]]
+if(categ[[i1]] == "fake_categ"){
+data1[[i1]][, "fake_categ"] <- factor(paste0("Line_", formatC(1:nrow(data1[[i2]]), width = nchar(nrow(data1[[i2]])), flag = "0")))
+}
+}
+tempo <- fun_check(data = alpha[[i1]], data.name = ifelse(length(alpha)== 1L, "alpha", paste0("alpha NUMBER ", i1)), prop = TRUE, length = 1, fun.name = function.name)
+if(tempo$problem == TRUE){
+stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+# end loop (checking inside list compartment)
+if(length(data1) > 1){
+if(length(unique(unlist(x)[ ! x == "fake_x"])) > 1){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE x ARGUMENT DOES NOT CONTAIN IDENTICAL COLUMN NAMES:\n", paste(unlist(x), collapse = " "), "\nX-AXIS OVERLAYING DIFFERENT VARIABLES?")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(length(data1) > 1){
+if(length(unique(unlist(y)[ ! y == "fake_y"])) > 1){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE y ARGUMENT DOES NOT CONTAIN IDENTICAL COLUMN NAMES:\n", paste(unlist(y), collapse = " "), "\nY-AXIS OVERLAYING DIFFERENT VARIABLES?")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+if(sum(geom %in% "geom_point") > 3){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT HAVE MORE THAN THREE \"geom_point\" ELEMENTS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(length(geom) - sum(geom %in% "geom_point") > 3){
+tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT HAVE MORE THAN THREE LINE ELEMENTS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+# x.lim management before transfo by x.log
+if(x.log != "no" & ! is.null(x.lim)){
+if(any(x.lim <= 0)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE x.log ARGUMENT SET TO ", x.log, ":\n", paste(x.lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(any( ! is.finite(if(x.log == "log10"){log10(x.lim)}else{log2(x.lim)}))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT RETURNS INF/NA WITH THE x.log ARGUMENT SET TO ", x.log, "\nAS SCALE COMPUTATION IS ", ifelse(x.log == "log10", "log10", "log2"), ":\n", paste(if(x.log == "log10"){log10(x.lim)}else{log2(x.lim)}, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(x.log != "no" & x.include.zero == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") x.log ARGUMENT SET TO ", x.log, " AND x.include.zero ARGUMENT SET TO TRUE -> x.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+x.include.zero <- FALSE
+}
+# end x.lim management before transfo by x.log
+# y.lim management before transfo by y.log
+if(y.log != "no" & ! is.null(y.lim)){
+if(any(y.lim <= 0)){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(any( ! is.finite(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT RETURNS INF/NA WITH THE y.log ARGUMENT SET TO ", y.log, "\nAS SCALE COMPUTATION IS ", ifelse(y.log == "log10", "log10", "log2"), ":\n", paste(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(y.log != "no" & y.include.zero == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") y.log ARGUMENT SET TO ", y.log, " AND y.include.zero ARGUMENT SET TO TRUE -> y.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+y.include.zero <- FALSE
+}
+# end y.lim management before transfo by y.log
+# end other checkings
+# reserved word checking
+#already done above
+# end reserved word checking
+# end second round of checking and data preparation
+
+
+# package checking
+fun_pack(req.package = c(
+"gridExtra", 
+"ggplot2", 
+"lemon", 
+"scales"
+), lib.path = lib.path)
+# packages Cairo and grid tested by fun_gg_point_rast()
+# end package checking
+
+
+
+
+# main code
+# axes management
+if(is.null(x.lim)){
+if(any(unlist(mapply(FUN = "[[", data1, x, SIMPLIFY = FALSE)) %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE x COLUMN IN data1 CONTAINS -Inf OR Inf VALUES THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+x.lim <- suppressWarnings(range(unlist(mapply(FUN = "[[", data1, x, SIMPLIFY = FALSE)), na.rm = TRUE, finite = TRUE)) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only. y.lim added here. If NULL, ok if y argument has values
+}else if(x.log != "no"){
+x.lim <- get(x.log)(x.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+if(x.log != "no"){
+if(any( ! is.finite(x.lim))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE x.log ARGUMENT SET TO ", x.log, ":\n", paste(x.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(suppressWarnings(all(x.lim %in% c(Inf, -Inf)))){ # happen when x is only NULL
+if(all(unlist(geom) %in% c("geom_vline", "geom_stick"))){
+tempo.cat <- paste0("ERROR IN ", function.name, " NOT POSSIBLE TO DRAW geom_vline OR geom_stick KIND OF LINES ALONE IF x.lim ARGUMENT IS SET TO NULL, SINCE NO X-AXIS DEFINED (", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT MUST BE NULL FOR THESE KIND OF LINES)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, " x.lim ARGUMENT MADE OF NA, -Inf OR Inf ONLY: ", paste(x.lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+x.lim.order <- order(x.lim) # to deal with inverse axis
+# print(x.lim.order)
+x.lim <- sort(x.lim)
+x.lim[1] <- x.lim[1] - abs(x.lim[2] - x.lim[1]) * ifelse(diff(x.lim.order) > 0, x.right.extra.margin, x.left.extra.margin) # diff(x.lim.order) > 0 means not inversed axis
+x.lim[2] <- x.lim[2] + abs(x.lim[2] - x.lim[1]) * ifelse(diff(x.lim.order) > 0, x.left.extra.margin, x.right.extra.margin) # diff(x.lim.order) > 0 means not inversed axis
+if(x.include.zero == TRUE){ # no need to check x.log != "no" because done before
+x.lim <- range(c(x.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
+}
+x.lim <- x.lim[x.lim.order]
+if(any(is.na(x.lim))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(is.null(y.lim)){
+if(any(unlist(mapply(FUN = "[[", data1, y, SIMPLIFY = FALSE)) %in% c(Inf, -Inf))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE y COLUMN IN data1 CONTAINS -Inf OR Inf VALUES THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+y.lim <- suppressWarnings(range(unlist(mapply(FUN = "[[", data1, y, SIMPLIFY = FALSE)), na.rm = TRUE, finite = TRUE)) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only. y.lim added here. If NULL, ok if y argument has values
+}else if(y.log != "no"){
+y.lim <- get(y.log)(y.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
+}
+if(y.log != "no"){
+if(any( ! is.finite(y.lim))){
+tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+}
+if(suppressWarnings(all(y.lim %in% c(Inf, -Inf)))){ # happen when y is only NULL
+if(all(unlist(geom) == "geom_vline")){
+tempo.cat <- paste0("ERROR IN ", function.name, " NOT POSSIBLE TO DRAW geom_vline KIND OF LINES ALONE IF y.lim ARGUMENT IS SET TO NULL, SINCE NO Y-AXIS DEFINED (", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT MUST BE NULL FOR THESE KIND OF LINES)")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, " y.lim ARGUMENT MADE OF NA, -Inf OR Inf ONLY: ", paste(y.lim, collapse = " "))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
 }
-
-
-######## fun_scale() #### select nice label numbers when setting number of ticks on an axis
-
-
-
-
-
-fun_scale <- function(n, lim, kind = "approx", lib.path = NULL){
-    # AIM
-    # attempt to select nice scale numbers when setting n ticks on a lim axis range
-    # ARGUMENTS
-    # n: desired number of main ticks on the axis (integer above 0)
-    # lim: vector of 2 numbers indicating the limit range of the axis. Order of the 2 values matters (for inverted axis). Can be log transformed values
-    # kind: either "approx" (approximative), "strict" (strict) or "strict.cl" (strict clean). If "approx", use the scales::trans_breaks() function to provide an easy to read scale of approximately n ticks spanning the range of the lim argument. If "strict", cut the range of the lim argument into n + 1 equidistant part and return the n numbers at each boundary. This often generates numbers uneasy to read. If "strict.cl", provide an easy to read scale of exactly n ticks, but sometimes not completely spanning the range of the lim argument
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # RETURN
-    # a vector of numbers
-    # REQUIRED PACKAGES
-    # if kind = "approx":
-    # ggplot2
-    # scales
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_round()
-    # EXAMPLES
-    # approximate number of main ticks
-    # ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "approx") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
-    # strict number of main ticks
-    # ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "strict") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
-    # strict "clean" number of main ticks
-    # ymin = 2 ; ymax = 3.101 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "strict.cl") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
-    # approximate number of main ticks, scale inversion
-    # ymin = 3.101 ; ymax = 2 ; n = 5 ; scale <- fun_scale(n = n, lim = c(ymin, ymax), kind = "approx") ; scale ; par(yaxt = "n", yaxs = "i", las = 1) ; plot(ymin:ymax, ymin:ymax, xlim = range(scale, ymin, ymax)[order(c(ymin, ymax))], ylim = range(scale, ymin, ymax)[order(c(ymin, ymax))], xlab = "DEFAULT SCALE", ylab = "NEW SCALE") ; par(yaxt = "s") ; axis(side = 2, at = scale)
-    # DEBUGGING
-    # n = 9 ; lim = c(2, 3.101) ; kind = "approx" ; lib.path = NULL # for function debugging
-    # n = 10 ; lim = c(1e-4, 1e6) ; kind = "approx" ; lib.path = NULL # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # end initial argument checking
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_round", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_round() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & isTRUE(all.equal(n, 0))){ # isTRUE(all.equal(n, 0)) equivalent to n == 0 but deals with floats (approx ok)
-        tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A NON NULL AND POSITIVE INTEGER")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE) # 
-    }
-    tempo <- fun_check(data = lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & all(diff(lim) == 0L)){ # isTRUE(all.equal(diff(lim), rep(0, length(diff(lim))))) not used because we strictly need zero as a result
-        tempo.cat <- paste0("ERROR IN ", function.name, ": lim ARGUMENT HAS A NULL RANGE (2 IDENTICAL VALUES)")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }else if(tempo$problem == FALSE & any(lim %in% c(Inf, -Inf))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = kind, options = c("approx", "strict", "strict.cl"), length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    lim.rank <- rank(lim) # to deal with inverted axis
-    lim <- sort(lim)
-    if(kind == "approx"){
-        # package checking
-        fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
-        fun_pack(req.package = c("scales"), lib.path = lib.path)
-        # end package checking
-        output <- ggplot2::ggplot_build(ggplot2::ggplot() + ggplot2::scale_y_continuous(
-            breaks = scales::trans_breaks(
-                trans = "identity", 
-                inv = "identity", 
-                n = n
-            ), 
-            limits = lim
-        ))$layout$panel_params[[1]]$y$breaks # pretty() alone is not appropriate: tempo.pret <-  pretty(seq(lim[1] ,lim[2], length.out = n)) ; tempo.pret[tempo.pret > = lim[1] & tempo.pret < = lim[2]]. # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks
-        if( ! is.null(attributes(output))){ # layout$panel_params[[1]]$y$breaks can be characters (labels of the axis). In that case, it has attributes that corresponds to positions
-            output <- unlist(attributes(output))
-        }
-        output <- output[ ! is.na(output)]
-    }else if(kind == "strict"){
-        output <- fun_round(seq(lim[1] ,lim[2], length.out = n), 2)
-    }else if(kind == "strict.cl"){
-        tempo.range <- diff(sort(lim))
-        tempo.max <- max(lim)
-        tempo.min <- min(lim)
-        mid <- tempo.min + (tempo.range/2) # middle of axis
-        tempo.inter <- tempo.range / (n + 1) # current interval between two ticks, between 0 and Inf
-        if(tempo.inter == 0L){ # isTRUE(all.equal(tempo.inter, rep(0, length(tempo.inter)))) not used because we strictly need zero as a result
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE INTERVAL BETWEEN TWO TICKS OF THE SCALE IS NULL. MODIFY THE lim OR n ARGUMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        log10.abs.lim <- 200
-        log10.range <- (-log10.abs.lim):log10.abs.lim
-        log10.vec <- 10^log10.range
-        round.vec <- c(5, 4, 3, 2.5, 2, 1.25, 1)
-        dec.table <- outer(log10.vec, round.vec) # table containing the scale units (row: power of ten from -201 to +199, column: the 5, 2.5, 2, 1.25, 1 notches
-        
-        
-        
-        # recover the number of leading zeros in tempo.inter
-        ini.scipen <- options()$scipen
-        options(scipen = -1000) # force scientific format
-        if(any(grepl(pattern = "\\+", x = tempo.inter))){ # tempo.inter > 1
-            power10.exp <- as.integer(substring(text = tempo.inter, first = (regexpr(pattern = "\\+", text = tempo.inter) + 1))) # recover the power of 10. Example recover 08 from 1e+08
-            mantisse <- as.numeric(substr(x = tempo.inter, start = 1, stop = (regexpr(pattern = "\\+", text = tempo.inter) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
-        }else if(any(grepl(pattern = "\\-", x = tempo.inter))){ # tempo.inter < 1
-            power10.exp <- as.integer(substring(text = tempo.inter, first = (regexpr(pattern = "\\-", text = tempo.inter)))) # recover the power of 10. Example recover 08 from 1e+08
-            mantisse <- as.numeric(substr(x = tempo.inter, start = 1, stop = (regexpr(pattern = "\\-", text = tempo.inter) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        tempo.scale <- dec.table[log10.range == power10.exp, ]
-        # new interval 
-        inter.select <- NULL
-        for(i1 in 1:length(tempo.scale)){
-            tempo.first.tick <- trunc((tempo.min + tempo.scale[i1]) / tempo.scale[i1]) * (tempo.scale[i1]) # this would be use to have a number not multiple of tempo.scale[i1]: ceiling(tempo.min) + tempo.scale[i1] * 10^power10.exp
-            tempo.last.tick <- tempo.first.tick + tempo.scale[i1] * (n - 1)
-            if((tempo.first.tick >= tempo.min) & (tempo.last.tick <= tempo.max)){
-                inter.select <- tempo.scale[i1]
-                break()
-            }
-        }
-        if(is.null(inter.select)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        options(scipen = ini.scipen) # restore the initial scientific penalty
-        # end new interval 
-        # centering the new scale 
-        tempo.mid <- trunc((mid + (-1:1) * inter.select) / inter.select) * inter.select # tempo middle tick closest to the middle axis
-        mid.tick <- tempo.mid[which.min(abs(tempo.mid - mid))]
-        if(isTRUE(all.equal(n, rep(1, length(n))))){ # isTRUE(all.equal(n, rep(1, length(n)))) is similar to n == 1L but deals with float
-            output <- mid.tick
-        }else if(isTRUE(all.equal(n, rep(2, length(n))))){ # isTRUE(all.equal(n, rep(0, length(n)))) is similar to n == 2L but deals with float
-            output <- mid.tick
-            tempo.min.dist <- mid.tick - inter.select - tempo.min
-            tempo.max.dist <- tempo.max - mid.tick + inter.select
-            if(tempo.min.dist <= tempo.max.dist){ # distance between lowest tick and bottom axis <= distance between highest tick and top axis. If yes, extra tick but at the top, otherwise at the bottom
-                output <- c(mid.tick, mid.tick + inter.select)
-            }else{
-                output <- c(mid.tick - inter.select, mid.tick)
-            }
-        }else if((n / 2 - trunc(n / 2)) > 0.1){ # > 0.1 to avoid floating point. Because result can only be 0 or 0.5. Thus, > 0.1 means odd number
-            output <- c(mid.tick - (trunc(n / 2):1) * inter.select, mid.tick, mid.tick + (1:trunc(n / 2)) * inter.select)
-        }else if((n / 2 - trunc(n / 2)) < 0.1){ # < 0.1 to avoid floating point. Because result can only be 0 or 0.5. Thus, < 0.1 means even number
-            tempo.min.dist <- mid.tick - trunc(n / 2) * inter.select - tempo.min
-            tempo.max.dist <- tempo.max - mid.tick + trunc(n / 2) * inter.select
-            if(tempo.min.dist <= tempo.max.dist){ # distance between lowest tick and bottom axis <= distance between highest tick and top axis. If yes, extra tick but at the bottom, otherwise at the top
-                output <- c(mid.tick - ((trunc(n / 2) - 1):1) * inter.select, mid.tick, mid.tick + (1:trunc(n / 2)) * inter.select)
-            }else{
-                output <- c(mid.tick - (trunc(n / 2):1) * inter.select, mid.tick, mid.tick + (1:(trunc(n / 2) - 1)) * inter.select)
-            }
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        # end centering the new scale 
-        # last check
-        if(min(output) < tempo.min){
-            output <- c(output[-1], max(output) + inter.select) # remove the lowest tick and add a tick at the top
-        }else if( max(output) > tempo.max){
-            output <- c(min(output) - inter.select, output[-length(output)])
-        }
-        if(min(output) < tempo.min | max(output) > tempo.max){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(is.na(output))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5 (NA GENERATION)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        # end last check
-    }else{
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 6")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(diff(lim.rank) < 0){
-        output <- rev(output)
-    }
-    return(output)
+y.lim.order <- order(y.lim) # to deal with inverse axis
+y.lim <- sort(y.lim)
+y.lim[1] <- y.lim[1] - abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.bottom.extra.margin, y.top.extra.margin) # diff(y.lim.order) > 0 means not inversed axis
+y.lim[2] <- y.lim[2] + abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.top.extra.margin, y.bottom.extra.margin) # diff(y.lim.order) > 0 means not inversed axis
+if(y.include.zero == TRUE){ # no need to check y.log != "no" because done before
+y.lim <- range(c(y.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
 }
-
-
-######## fun_inter_ticks() #### define coordinates of secondary ticks
-
-
-fun_inter_ticks <- function(
-    lim, 
-    log = "log10", 
-    breaks = NULL, 
-    n = NULL, 
-    warn.print = TRUE
-){
-    # AIM
-    # define coordinates and values of secondary ticks
-    # ARGUMENTS
-    # lim: vector of 2 numbers indicating the limit range of the axis. Order of the 2 values matters (for inverted axis). If log argument is "log2" or "log10", values in lim must be already log transformed. Thus, negative or zero values are allowed
-    # log: either "log2" (values in the lim argument are log2 transformed) or "log10" (values in the lim argument are log10 transformed), or "no"
-    # breaks: mandatory vector of numbers indicating the main ticks values/positions when log argument is "no". Ignored when log argument is "log2" or "log10"
-    # n: number of secondary ticks between each main tick when log argument is "no". Ignored when log argument is "log2" or "log10"
-    # warn.print: logical. Print potential warning messages at the end of the execution? If FALSE, warning messages are never printed, but can still be recovered in the returned list
-    # RETURN
-    # a list containing
-    # $log: value of the log argument used
-    # $coordinates: the coordinates of the secondary ticks on the axis, between the lim values
-    # $values: the corresponding values associated to each coordinate (with log scale, 2^$values or 10^$values is equivalent to the labels of the axis)
-    # $warn: the potential warning messages. Use cat() for proper display. NULL if no warning
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # no log scale
-    # fun_inter_ticks(lim = c(-4,4), log = "no", breaks = c(-2, 0, 2), n = 3)
-    # fun_inter_ticks(lim = c(10, 0), log = "no", breaks = c(10, 8, 6, 4, 2, 0), n = 4)
-    # log2
-    # fun_inter_ticks(lim = c(-4,4), log = "log2")
-    # log10
-    # fun_inter_ticks(lim = c(-2,3), log = "log10")
-    # DEBUGGING
-    # lim = c(2, 3.101) ; log = "no" ; breaks = NULL ; n = NULL ; warn.print = TRUE # for function debugging
-    # lim = c(0, 26.5) ; log = "no" ; breaks = c(0, 10, 20) ; n = 3 # for function debugging
-    # lim = c(10, 0); log = "no"; breaks = c(10, 8, 6, 4, 2, 0); n = 4 # for function debugging
-    # lim = c(-10, -20); log = "no"; breaks = c(-20, -15, -10); n = 4 # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check"
-    )
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED ", i1, "() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end required function checking
-    # argument primary checking
-    # arg with no default values
-    mandat.args <- c(
-        "lim"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # using fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(breaks)){
-        tempo <- fun_check(data = breaks, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(n)){
-        tempo <- fun_check(data = n, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = warn.print, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA
-    if(any(is.na(lim)) | any(is.na(log)) | any(is.na(breaks)) | any(is.na(n)) | any(is.na(warn.print))){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nNO ARGUMENT CAN HAVE NA VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA
-    # management of NULL
-    if(is.null(lim) | is.null(log)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nTHESE ARGUMENTS\nlim\nlog\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL
-    if(all(diff(lim) == 0L)){ # isTRUE(all.equal(diff(lim), rep(0, length(diff(lim))))) not used because we strictly need zero as a result
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nlim ARGUMENT HAS A NULL RANGE (2 IDENTICAL VALUES): ", paste(lim, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if(any(lim %in% c(Inf, -Inf))){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nlim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(log == "no" & is.null(breaks)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT CANNOT BE NULL IF log ARGUMENT IS \"no\"")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(breaks)){
-        if(length(breaks) < 2){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT MUST HAVE 2 VALUES AT LEAST (OTHERWISE, INTER TICK POSITIONS CANNOT BE COMPUTED): ", paste(breaks, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! isTRUE(all.equal(diff(sort(breaks)), rep(diff(sort(breaks))[1], length(diff(sort(breaks))))))){ # isTRUE(all.equal(n, 0)) equivalent to n == 0 but deals with floats (approx ok)
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nbreaks ARGUMENT MUST HAVE EQUIDISTANT VALUES (OTHERWISE, EQUAL NUMBER OF INTER TICK BETWEEN MAIN TICKS CANNOT BE COMPUTED): ", paste(breaks, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if( ! is.null(n)){
-        if(n <= 0){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nn ARGUMENT MUST BE A POSITIVE AND NON NULL INTEGER: ", paste(n, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end second round of checking and data preparation
-    # main code
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    lim.rank <- rank(lim) # to deal with inverse axis
-    if(log != "no"){
-        ini.scipen <- options()$scipen
-        options(scipen = -1000) # force scientific format
-        power10.exp <- as.integer(substring(text = 10^lim, first = (regexpr(pattern = "\\+|\\-", text = 10^lim)))) # recover the power of 10, i.e., integer part of lim. Example recover 08 from 1e+08. Works for log2
-        # mantisse <- as.numeric(substr(x = 10^lim, start = 1, stop = (regexpr(pattern = "\\+|\\-", text = 10^lim) - 2))) # recover the mantisse. Example recover 1.22 from 1.22e+08
-        options(scipen = ini.scipen) # restore the initial scientific penalty
-        tick.pos <- unique(as.vector(outer(2:10, ifelse(log == "log2", 2, 10)^((power10.exp[1] - ifelse(diff(lim.rank) > 0, 1, -1)):(power10.exp[2] + ifelse(diff(lim.rank) > 0, 1, -1)))))) # use log10(2:10) even if log2: it is to get log values between 0 and 1
-        tick.pos <- sort(tick.pos, decreasing = ifelse(diff(lim.rank) > 0, FALSE, TRUE))
-        if(log == "log2"){
-            tick.values <- tick.pos[tick.pos >= min(2^lim) & tick.pos <= max(2^lim)]
-            tick.pos <- log2(tick.values)
-        }else if(log == "log10"){
-            tick.values <- tick.pos[tick.pos >= min(10^lim) & tick.pos <= max(10^lim)]
-            tick.pos <- log10(tick.values)
-        }
-    }else{
-        # if(length(breaks) > 1){ # not required because already checked above
-        breaks.rank <- rank(c(breaks[1], breaks[length(breaks)]))
-        if(diff(breaks.rank) != diff(lim.rank)){
-            breaks <- sort(breaks, decreasing = ifelse(diff(lim.rank) < 0, TRUE, FALSE))
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") VALUES IN breaks ARGUMENT NOT IN THE SAME ORDER AS IN lim ARGUMENT -> VALUES REORDERED AS IN lim: ", paste(breaks, collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            breaks.rank <- rank(c(breaks[1], breaks[length(breaks)]))
-        }
-        # }
-        main.tick.dist <- mean(diff(breaks), na.rm = TRUE)
-        tick.dist <- main.tick.dist / (n + 1)
-        tempo.extra.margin <- max(abs(diff(breaks)), na.rm = TRUE)
-        tick.pos <- seq(
-            if(diff(breaks.rank) > 0){breaks[1] - tempo.extra.margin}else{breaks[1] + tempo.extra.margin}, 
-            if(diff(breaks.rank) > 0){breaks[length(breaks)] + tempo.extra.margin}else{breaks[length(breaks)] - tempo.extra.margin}, 
-            by = tick.dist
-        )
-        tick.pos <- tick.pos[tick.pos >= min(lim) & tick.pos <= max(lim)]
-        tick.values <- tick.pos
-    }
-    if(any(is.na(tick.pos) | ! is.finite(tick.pos))){ 
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, ": NA or Inf GENERATED FOR THE INTER TICK POSITIONS: ", paste(tick.pos, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(tick.pos) == 0L){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NO INTER TICKS COMPUTED BETWEEN THE LIMITS INDICATED: ", paste(lim, collapse = " "))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    output <- list(log = log, coordinates = tick.pos, values = tick.values, warn = warn)
-    if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE)) # to recover the warning messages, see $warn
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    return(output)
+y.lim <- y.lim[y.lim.order]
+if(any(is.na(y.lim))){
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
 }
-
-
-######## fun_post_plot() #### set graph param after plotting (axes redesign for instance)
-
+# end axes management
 
 
 
 
-fun_post_plot <- function(
-    x.side = 0, 
-    x.log.scale = FALSE, 
-    x.categ = NULL, 
-    x.categ.pos = NULL, 
-    x.lab = "", 
-    x.axis.size = 1.5, 
-    x.label.size = 1.5, 
-    x.dist.legend = 0.5, 
-    x.nb.inter.tick = 1, 
-    y.side = 0, 
-    y.log.scale = FALSE, 
-    y.categ = NULL, 
-    y.categ.pos = NULL, 
-    y.lab = "", 
-    y.axis.size = 1.5, 
-    y.label.size = 1.5, 
-    y.dist.legend = 0.5, 
-    y.nb.inter.tick = 1, 
-    text.angle = 90, 
-    tick.length = 0.5, 
-    sec.tick.length = 0.3, 
-    bg.color = NULL, 
-    grid.lwd = NULL, 
-    grid.col = "white", 
-    corner.text = "", 
-    corner.text.size = 1, 
-    just.label.add = FALSE, 
-    par.reset = FALSE, 
-    custom.par = NULL
-){
-    # AIM
-    # redesign axis. If x.side = 0, y.side = 0, the function just adds text at topright of the graph and reset par() for next graphics and provides outputs (see below)
-    # provide also positions for legend or additional text on the graph
-    # use fun_prior_plot() before this function for initial inactivation of the axis drawings
-    # ARGUMENTS
-    # x.side: axis at the bottom (1) or top (3) of the region figure. Write 0 for no change
-    # x.log.scale: Log scale for the x-axis? Either TRUE or FALSE
-    # x.categ: character vector representing the classes (levels()) to specify when the x-axis is qualititative(stripchart, boxplot)
-    # x.categ.pos: position of the classes names (numeric vector of identical length than x.categ). If left NULL, this will be 1:length(levels())
-    # x.lab: label of the x-axis. If x.side == 0 and x.lab != "", then x.lab is printed
-    # x.axis.size: positive numeric. Increase or decrease the size of the x axis numbers. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2. Also control the size of displayed categories
-    # x.label.size: positive numeric. Increase or decrease the size of the x axis legend text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
-    # x.dist.legend: increase the number to move x-axis legends away in inches (first number of mgp argument of par() but in inches)
-    # x.nb.inter.tick: number of secondary ticks between main ticks on x-axis (only if not log scale). 0 means no secondary ticks
-    # y.side: axis at the left (2) or right (4) of the region figure. Write 0 for no change
-    # y.log.scale: Log scale for the y-axis? Either TRUE or FALSE
-    # y.categ: classes (levels()) to specify when the y-axis is qualititative(stripchart, boxplot)
-    # y.categ.pos: position of the classes names (numeric vector of identical length than y.categ). If left NULL, this will be 1:length(levels())
-    # y.lab: label of the y-axis. If y.side == 0 and y.lab != "", then y.lab is printed
-    # y.axis.size: positive numeric. Increase or decrease the size of the y axis numbers. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2. Also control the size of displayed categories
-    # y.label.size: positive numeric. Increase or decrease the size of the y axis legend text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
-    # y.dist.legend: increase the number to move y-axis legends away in inches (first number of mgp argument of par() but in inches)
-    # y.nb.inter.tick: number of secondary ticks between main ticks on y-axis (only if not log scale). 0 means non secondary ticks
-    # text.angle: angle of the text when axis is qualitative
-    # tick.length: length of the main ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
-    # sec.tick.length: length of the secondary ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
-    # bg.color: background color of the plot region. NULL for no color. BEWARE: cover/hide an existing plot !
-    # grid.lwd: if non NULL, activate the grid line (specify the line width)
-    # grid.col: grid line color (only if grid.lwd non NULL)
-    # corner.text: text to add at the top right corner of the window
-    # corner.text.size: positive numeric. Increase or decrease the size of the text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
-    # par.reset: to reset all the graphics parameters. BEWARE: TRUE can generate display problems, mainly in graphic devices with multiple figure regions
-    # just.label.add: just add axis labels (legend)? Either TRUE or FALSE. If TRUE, at least (x.side == 0 & x.lab != "") or (y.side == 0 & y.lab != "") must be set to display the corresponding x.lab or y.lab
-    # custom.par: list that provides the parameters that reset all the graphics parameters. BEWARE: if NULL and par.reset == TRUE, the default par() parameters are used
-    # RETURN
-    # a list containing: 
-    # $x.mid.left.dev.region: middle of the left margin of the device region, in coordinates of the x-axis
-    # $x.left.dev.region: left side of the left margin (including the potential margin of the device region), in coordinates of the x-axis
-    # $x.mid.right.dev.region: middle of the right margin of the device region, in coordinates of the x-axis
-    # $x.right.dev.region: right side of the right margin (including the potential margin of the device region), in coordinates of the x-axis
-    # $x.mid.left.fig.region: middle of the left margin of the figure region, in coordinates of the x-axis
-    # $x.left.fig.region: left side of the left margin, in coordinates of the x-axis
-    # $x.mid.right.fig.region: middle of the right margin of the figure region, in coordinates of the x-axis
-    # $x.right.fig.region: right side of the right margin, in coordinates of the x-axis
-    # $x.left.plot.region: left side of the plot region, in coordinates of the x-axis
-    # $x.right.plot.region: right side of the plot region, in coordinates of the x-axis
-    # $x.mid.plot.region: middle of the plot region, in coordinates of the x-axis
-    # $y.mid.bottom.dev.region: middle of the bottom margin of the device region, in coordinates of the y-axis
-    # $y.bottom.dev.region: bottom side of the bottom margin (including the potential margin of the device region), in coordinates of the y-axis
-    # $y.mid.top.dev.region: middle of the top margin of the device region, in coordinates of the y-axis
-    # $y.top.dev.region: top side of the top margin (including the potential margin of the device region), in coordinates of the y-axis
-    # $y.mid.bottom.fig.region: middle of the bottom margin of the figure region, in coordinates of the y-axis
-    # $y.bottom.fig.region: bottom of the bottom margin of the figure region, in coordinates of the y-axis
-    # $y.mid.top.fig.region: middle of the top margin of the figure region, in coordinates of the y-axis
-    # $y.top.fig.region: top of the top margin of the figure region, in coordinates of the y-axis
-    # $y.top.plot.region: top of the plot region, in coordinates of the y-axis
-    # $y.bottom.plot.region: bottom of the plot region, in coordinates of the y-axis
-    # $y.mid.plot.region: middle of the plot region, in coordinates of the y-axis
-    # $text: warning text
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_open() to reinitialize graph parameters if par.reset = TRUE and custom.par = NULL
-    # EXAMPLES
-    # Example of log axis with log y-axis and unmodified x-axis:
-    # prior.par <- fun_prior_plot(param.reinitial = TRUE, xlog.scale = FALSE, ylog.scale = TRUE, remove.label = TRUE, remove.x.axis = FALSE, remove.y.axis = TRUE, down.space = 1, left.space = 1, up.space = 1, right.space = 1, orient = 1, dist.legend = 0.5, tick.length = 0.5, box.type = "n", amplif.label = 1, amplif.axis = 1, display.extend = FALSE, return.par = TRUE) ; plot(1:100, log = "y") ; fun_post_plot(y.side = 2, y.log.scale = prior.par$ylog, x.lab = "Values", y.lab = "TEST", y.axis.size = 1.25, y.label.size = 1.5, y.dist.legend = 0.7, just.label.add = ! prior.par$ann)
-    # Example of log axis with redrawn x-axis and y-axis:
-    # prior.par <- fun_prior_plot(param.reinitial = TRUE) ; plot(1:100) ; fun_post_plot(x.side = 1, x.lab = "Values", y.side = 2, y.lab = "TEST", y.axis.size = 1, y.label.size = 2, y.dist.legend = 0.6)
-    # Example of title easily added to a plot:
-    # plot(1:100) ; para <- fun_post_plot(corner.text = "TITLE ADDED") # try also: par(xpd = TRUE) ; text(x = para$x.mid.left.fig.region, y = para$y.mid.top.fig.region, labels = "TITLE ADDED", cex = 0.5)
-    # example with margins in the device region:
-    # windows(5,5) ; fun_prior_plot(box.type = "o") ; par(mai=c(0.5,0.5,0.5,0.5), omi = c(0.25,0.25,1,0.25), xaxs = "i", yaxs = "i") ; plot(0:10) ; a <- fun_post_plot(x.side = 0, y.side = 0) ; x <- c(a$x.mid.left.dev.region, a$x.left.dev.region, a$x.mid.right.dev.region, a$x.right.dev.region, a$x.mid.left.fig.region, a$x.left.fig.region, a$x.mid.right.fig.region, a$x.right.fig.region, a$x.right.plot.region, a$x.left.plot.region, a$x.mid.plot.region) ; y <- c(a$y.mid.bottom.dev.region, a$y.bottom.dev.region, a$y.mid.top.dev.region, a$y.top.dev.region, a$y.mid.bottom.fig.region, a$y.bottom.fig.region, a$y.mid.top.fig.region, a$y.top.fig.region, a$y.top.plot.region, a$y.bottom.plot.region, a$y.mid.plot.region) ; par(xpd = NA) ; points(x = rep(5, length(y)), y = y, pch = 16, col = "red") ; text(x = rep(5, length(y)), y = y, c("y.mid.bottom.dev.region", "y.bottom.dev.region", "y.mid.top.dev.region", "y.top.dev.region", "y.mid.bottom.fig.region", "y.bottom.fig.region", "y.mid.top.fig.region", "y.top.fig.region", "y.top.plot.region", "y.bottom.plot.region", "y.mid.plot.region"), cex = 0.65, col = grey(0.25)) ; points(y = rep(5, length(x)), x = x, pch = 16, col = "blue") ; text(y = rep(5, length(x)), x = x, c("x.mid.left.dev.region", "x.left.dev.region", "x.mid.right.dev.region", "x.right.dev.region", "x.mid.left.fig.region", "x.left.fig.region", "x.mid.right.fig.region", "x.right.fig.region", "x.right.plot.region", "x.left.plot.region", "x.mid.plot.region"), cex = 0.65, srt = 90, col = grey(0.25))
-    # DEBUGGING
-    # x.side = 0 ; x.log.scale = FALSE ; x.categ = NULL ; x.categ.pos = NULL ; x.lab = "" ; x.axis.size = 1.5 ; x.label.size = 1.5 ; x.dist.legend = 1 ; x.nb.inter.tick = 1 ; y.side = 0 ; y.log.scale = FALSE ; y.categ = NULL ; y.categ.pos = NULL ; y.lab = "" ; y.axis.size = 1.5 ; y.label.size = 1.5 ; y.dist.legend = 0.7 ; y.nb.inter.tick = 1 ; text.angle = 90 ; tick.length = 0.5 ; sec.tick.length = 0.3 ; bg.color = NULL ; grid.lwd = NULL ; grid.col = "white" ; corner.text = "" ; corner.text.size = 1 ; just.label.add = FALSE ; par.reset = FALSE ; custom.par = NULL # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_open", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_open() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = x.side, options = c(0, 1, 3), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.log.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(x.categ)){
-        tempo <- fun_check(data = x.categ, class = "character", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(x.categ.pos)){
-        tempo <- fun_check(data = x.categ.pos, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = x.lab, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.axis.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.label.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.nb.inter.tick, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.side, options = c(0, 2, 4), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.log.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(y.categ)){
-        tempo <- fun_check(data = y.categ, class = "character", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(y.categ.pos)){
-        tempo <- fun_check(data = y.categ.pos, class = "vector", mode = "numeric", fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = y.lab, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.axis.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.label.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.nb.inter.tick, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = text.angle, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = sec.tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(bg.color)){
-        tempo <- fun_check(data = bg.color, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-        if( ! (bg.color %in% colors() | grepl(pattern = "^#", bg.color))){ # check color
-            tempo.cat <- paste0("ERROR IN ", function.name, ": bg.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # OR A COLOR NAME GIVEN BY colors()")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    if( ! is.null(grid.lwd)){
-        tempo <- fun_check(data = grid.lwd, class = "vector", mode = "numeric", neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(grid.col)){
-        tempo <- fun_check(data = grid.col, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-        if( ! (grid.col %in% colors() | grepl(pattern = "^#", grid.col))){ # check color
-            tempo.cat <- paste0("ERROR IN ", function.name, ": grid.col ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # OR A COLOR NAME GIVEN BY colors()")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = corner.text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = corner.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = just.label.add, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = par.reset, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(custom.par)){
-        tempo <- fun_check(data = custom.par, typeof = "list", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    text <- NULL
-    par(tcl = -par()$mgp[2] * tick.length)
-    if(x.log.scale == TRUE){
-        grid.coord.x <- c(10^par("usr")[1], 10^par("usr")[2])
-    }else{
-        grid.coord.x <- c(par("usr")[1], par("usr")[2])
-    }
-    if(y.log.scale == TRUE){
-        grid.coord.y <- c(10^par("usr")[3], 10^par("usr")[4])
-    }else{
-        grid.coord.y <- c(par("usr")[3], par("usr")[4])
-    }
-    if( ! is.null(bg.color)){
-        rect(grid.coord.x[1], grid.coord.y[1], grid.coord.x[2], grid.coord.y[2], col = bg.color, border = NA)
-    }
-    if( ! is.null(grid.lwd)){
-        grid(nx = NA, ny = NULL, col = grid.col, lty = 1, lwd = grid.lwd)
-    }
-    if(x.log.scale == TRUE){
-        x.mid.left.dev.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
-        x.left.dev.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1]) # in x coordinates
-        x.mid.right.dev.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
-        x.right.dev.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2])) # in x coordinates
-        x.mid.left.fig.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
-        x.left.fig.region <- 10^(par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1]) # in x coordinates
-        x.mid.right.fig.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
-        x.right.fig.region <- 10^(par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2])) # in x coordinates
-        x.left.plot.region <- 10^par("usr")[1] # in x coordinates, left of the plot region (according to x scale)
-        x.right.plot.region <- 10^par("usr")[2] # in x coordinates, right of the plot region (according to x scale)
-        x.mid.plot.region <- 10^((par("usr")[2] + par("usr")[1]) / 2) # in x coordinates, right of the plot region (according to x scale)
-    }else{
-        x.mid.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
-        x.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1]) # in x coordinates
-        x.mid.right.dev.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
-        x.right.dev.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) + ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * (1 - par("omd")[2])) # in x coordinates
-        x.mid.left.fig.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] / 2) # in x coordinates, to position axis labeling at the bottom of the graph (according to x scale)
-        x.left.fig.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1]) # in x coordinates
-        x.mid.right.fig.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2]) / 2) # in x coordinates, to position axis labeling at the top of the graph (according to x scale)
-        x.right.fig.region <- (par("usr")[2] + ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * (1 - par("plt")[2])) # in x coordinates
-        x.left.plot.region <- par("usr")[1] # in x coordinates, left of the plot region (according to x scale)
-        x.right.plot.region <- par("usr")[2] # in x coordinates, right of the plot region (according to x scale)
-        x.mid.plot.region <- (par("usr")[2] + par("usr")[1]) / 2 # in x coordinates, right of the plot region (according to x scale)
-    }
-    if(y.log.scale == TRUE){
-        y.mid.bottom.dev.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (par("omd")[3] / 2)) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
-        y.bottom.dev.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * par("omd")[3]) # in y coordinates
-        y.mid.top.dev.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
-        y.top.dev.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4])) # in y coordinates
-        y.mid.bottom.fig.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] / 2) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
-        y.bottom.fig.region <- 10^(par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3]) # in y coordinates
-        y.mid.top.fig.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
-        y.top.fig.region <- 10^(par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4])) # in y coordinates
-        y.top.plot.region <- 10^par("usr")[4] # in y coordinates, top of the plot region (according to y scale)
-        y.bottom.plot.region <- 10^par("usr")[3] # in y coordinates, bottom of the plot region (according to y scale)
-        y.mid.plot.region <- (par("usr")[3] + par("usr")[4]) / 2 # in x coordinates, right of the plot region (according to x scale)
-    }else{
-        y.mid.bottom.dev.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (par("omd")[3] / 2)) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
-        y.bottom.dev.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] - ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * par("omd")[3]) # in y coordinates
-        y.mid.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
-        y.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4])) # in y coordinates
-        y.mid.bottom.fig.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3] / 2) # in y coordinates, to position axis labeling at the bottom of the graph (according to y scale). Ex mid.bottom.space
-        y.bottom.fig.region <- (par("usr")[3] - ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * par("plt")[3]) # in y coordinates
-        y.mid.top.fig.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) / 2) # in y coordinates, to position axis labeling at the top of the graph (according to y scale). Ex mid.top.space
-        y.top.fig.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4])) # in y coordinates
-        y.top.plot.region <- par("usr")[4] # in y coordinates, top of the plot region (according to y scale)
-        y.bottom.plot.region <- par("usr")[3] # in y coordinates, bottom of the plot region (according to y scale)
-        y.mid.plot.region <- ((par("usr")[3] + par("usr")[4]) / 2) # in x coordinates, right of the plot region (according to x scale)
-    }
-    if(any(sapply(FUN = all.equal, c(1, 3), x.side) == TRUE)){
-        par(xpd=FALSE, xaxt="s")
-        if(is.null(x.categ) & x.log.scale == TRUE){
-            if(any(par()$xaxp[1:2] == 0L)){ # any(sapply(FUN = all.equal, par()$xaxp[1:2], 0) == TRUE) not used because we strictly need zero as a result. Beware: write "== TRUE", because the result is otherwise character and a warning message appears using any()
-                if(par()$xaxp[1] == 0L){ # isTRUE(all.equal(par()$xaxp[1], 0)) not used because we strictly need zero as a result
-                    par(xaxp = c(10^-30, par()$xaxp[2:3])) # because log10(par()$xaxp[1] == 0) == -Inf
-                }
-                if(par()$xaxp[2] == 0L){ # isTRUE(all.equal(par()$xaxp[1], 0)) not used because we strictly need zero as a result
-                    par(xaxp = c(par()$xaxp[1], 10^-30, par()$xaxp[3])) # because log10(par()$xaxp[2] == 0) == -Inf
-                }
-            }
-            axis(side = x.side, at = c(10^par()$usr[1], 10^par()$usr[2]), labels=rep("", 2), lwd=1, lwd.ticks = 0) # draw the axis line
-            mtext(side = x.side, text = x.lab, line = x.dist.legend / 0.2, las = 0, cex = x.label.size)
-            par(tcl = -par()$mgp[2] * sec.tick.length) # length of the secondary ticks are reduced
-            suppressWarnings(rug(10^outer(c((log10(par("xaxp")[1]) -1):log10(par("xaxp")[2])), log10(1:10), "+"), ticksize = NA, side = x.side)) # ticksize = NA to allow the use of par()$tcl value
-            par(tcl = -par()$mgp[2] * tick.length) # back to main ticks
-            axis(side = x.side, at = c(1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10), labels = expression(10^-15, 10^-14, 10^-13, 10^-12, 10^-11, 10^-10, 10^-9, 10^-8, 10^-7, 10^-6, 10^-5, 10^-4, 10^-3, 10^-2, 10^-1, 10^0, 10^1, 10^2, 10^3, 10^4, 10^5, 10^6, 10^7, 10^8, 10^9, 10^10), lwd = 0, lwd.ticks = 1, cex.axis = x.axis.size)
-            x.text <- 10^par("usr")[2]
-        }else if(is.null(x.categ) & x.log.scale == FALSE){
-            axis(side=x.side, at=c(par()$usr[1], par()$usr[2]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
-            axis(side=x.side, at=round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), cex.axis = x.axis.size) # axis(side=x.side, at=round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), labels = format(round(seq(par()$xaxp[1], par()$xaxp[2], length.out=par()$xaxp[3]+1), 2), big.mark=','), cex.axis = x.axis.size) # to get the 1000 comma separator
-            mtext(side = x.side, text = x.lab, line = x.dist.legend / 0.2, las = 0, cex = x.label.size)
-            if(x.nb.inter.tick > 0){
-                inter.tick.unit <- (par("xaxp")[2] - par("xaxp")[1]) / par("xaxp")[3]
-                par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
-                suppressWarnings(rug(seq(par("xaxp")[1] - 10 * inter.tick.unit, par("xaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + x.nb.inter.tick)), ticksize = NA, x.side)) # ticksize = NA to allow the use of par()$tcl value
-                par(tcl = -par()$mgp[2] * tick.length) # back to main ticks
-            }
-            x.text <- par("usr")[2]
-        }else if(( ! is.null(x.categ)) & x.log.scale == FALSE){
-            if(is.null(x.categ.pos)){
-                x.categ.pos <- 1:length(x.categ)
-            }else if(length(x.categ.pos) != length(x.categ)){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": x.categ.pos MUST BE THE SAME LENGTH AS x.categ")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            par(xpd = TRUE)
-            if(isTRUE(all.equal(x.side, 1))){ #isTRUE(all.equal(x.side, 1)) is similar to x.side == 1L but deals with float
-                segments(x0 = x.left.plot.region, x1 = x.right.plot.region, y0 = y.bottom.plot.region, y1 = y.bottom.plot.region) # draw the line of the axis
-                text(x = x.categ.pos, y = y.mid.bottom.fig.region, labels = x.categ, srt = text.angle, cex = x.axis.size)
-            }else if(isTRUE(all.equal(x.side, 3))){ #isTRUE(all.equal(x.side, 1)) is similar to x.side == 3L but deals with float
-                segments(x0 = x.left.plot.region, x1 = x.right.plot.region, y0 = y.top.plot.region, y1 = y.top.plot.region) # draw the line of the axis
-                text(x = x.categ.pos, y = y.mid.top.fig.region, labels = x.categ, srt = text.angle, cex = x.axis.size)
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ARGUMENT x.side CAN ONLY BE 1 OR 3")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            par(xpd = FALSE)
-            x.text <- par("usr")[2]
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": PROBLEM WITH THE x.side (", x.side ,") OR x.log.scale (", x.log.scale,") ARGUMENTS")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else{
-        x.text <- par("usr")[2]
-    }
-    if(any(sapply(FUN = all.equal, c(2, 4), y.side) == TRUE)){
-        par(xpd=FALSE, yaxt="s")
-        if(is.null(y.categ) & y.log.scale == TRUE){
-            if(any(par()$yaxp[1:2] == 0L)){ # any(sapply(FUN = all.equal, par()$yaxp[1:2], 0) == TRUE) not used because we strictly need zero as a result. Beware: write "== TRUE", because the result is otherwise character and a warning message appears using any()
-                if(par()$yaxp[1] == 0L){ # strict zero needed
-                    par(yaxp = c(10^-30, par()$yaxp[2:3])) # because log10(par()$yaxp[1] == 0) == -Inf
-                }
-                if(par()$yaxp[2] == 0L){ # strict zero needed
-                    par(yaxp = c(par()$yaxp[1], 10^-30, par()$yaxp[3])) # because log10(par()$yaxp[2] == 0) == -Inf
-                }
-            }
-            axis(side=y.side, at=c(10^par()$usr[3], 10^par()$usr[4]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
-            par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
-            suppressWarnings(rug(10^outer(c((log10(par("yaxp")[1])-1):log10(par("yaxp")[2])), log10(1:10), "+"), ticksize = NA, side = y.side)) # ticksize = NA to allow the use of par()$tcl value
-            par(tcl = -par()$mgp[2] * tick.length) # back to main tick length
-            axis(side = y.side, at = c(1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10), labels = expression(10^-15, 10^-14, 10^-13, 10^-12, 10^-11, 10^-10, 10^-9, 10^-8, 10^-7, 10^-6, 10^-5, 10^-4, 10^-3, 10^-2, 10^-1, 10^0, 10^1, 10^2, 10^3, 10^4, 10^5, 10^6, 10^7, 10^8, 10^9, 10^10), lwd = 0, lwd.ticks = 1, cex.axis = y.axis.size)
-            y.text <- 10^(par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
-            mtext(side = y.side, text = y.lab, line = y.dist.legend / 0.2, las = 0, cex = y.label.size)
-        }else if(is.null(y.categ) & y.log.scale == FALSE){
-            axis(side=y.side, at=c(par()$usr[3], par()$usr[4]), labels=rep("", 2), lwd=1, lwd.ticks=0) # draw the axis line
-            axis(side=y.side, at=round(seq(par()$yaxp[1], par()$yaxp[2], length.out=par()$yaxp[3]+1), 2), cex.axis = y.axis.size)
-            mtext(side = y.side, text = y.lab, line = y.dist.legend / 0.2, las = 0, cex = y.label.size)
-            if(y.nb.inter.tick > 0){
-                inter.tick.unit <- (par("yaxp")[2] - par("yaxp")[1]) / par("yaxp")[3]
-                par(tcl = -par()$mgp[2] * sec.tick.length) # length of the ticks are reduced
-                suppressWarnings(rug(seq(par("yaxp")[1] - 10 * inter.tick.unit, par("yaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + y.nb.inter.tick)), ticksize = NA, side=y.side)) # ticksize = NA to allow the use of par()$tcl value
-                par(tcl = -par()$mgp[2] * tick.length) # back to main tick length
-            }
-            y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
-        }else if(( ! is.null(y.categ)) & y.log.scale == FALSE){
-            if(is.null(y.categ.pos)){
-                y.categ.pos <- 1:length(y.categ)
-            }else if(length(y.categ.pos) != length(y.categ)){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": y.categ.pos MUST BE THE SAME LENGTH AS y.categ")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            axis(side = y.side, at = y.categ.pos, labels = rep("", length(y.categ)), lwd=0, lwd.ticks=1) # draw the line of the axis
-            par(xpd = TRUE)
-            if(isTRUE(all.equal(y.side, 2))){ #isTRUE(all.equal(y.side, 2)) is similar to y.side == 2L but deals with float
-                text(x = x.mid.left.fig.region, y = y.categ.pos, labels = y.categ, srt = text.angle, cex = y.axis.size)
-            }else if(isTRUE(all.equal(y.side, 4))){ # idem
-                text(x = x.mid.right.fig.region, y = y.categ.pos, labels = y.categ, srt = text.angle, cex = y.axis.size)
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ARGUMENT y.side CAN ONLY BE 2 OR 4")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            par(xpd = FALSE)
-            y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": PROBLEM WITH THE y.side (", y.side ,") OR y.log.scale (", y.log.scale,") ARGUMENTS")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else{
-        y.text <- (par("usr")[4] + (par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3]) * (1 - par("plt")[4]))
-    }
-    par(xpd=NA)
-    text(x = x.mid.right.fig.region, y = y.text, corner.text, adj=c(1, 1.1), cex = corner.text.size) # text at the topright corner. Replace x.right.fig.region by x.text if text at the right edge of the plot region
-    if(just.label.add == TRUE & isTRUE(all.equal(x.side, 0)) & x.lab != ""){
-        text(x = x.mid.plot.region, y = y.mid.bottom.fig.region, x.lab, adj=c(0.5, 0.5), cex = x.label.size) # x label
-    }
-    if(just.label.add == TRUE & isTRUE(all.equal(y.side, 0)) & y.lab != ""){
-        text(x = y.mid.plot.region, y = x.mid.left.fig.region, y.lab, adj=c(0.5, 0.5), cex = y.label.size) # x label
-    }
-    par(xpd=FALSE)
-    if(par.reset == TRUE){
-        tempo.par <- fun_open(pdf = FALSE, return.output = TRUE)
-        invisible(dev.off()) # close the new window
-        if( ! is.null(custom.par)){
-            if( ! names(custom.par) %in% names(tempo.par$ini.par)){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": custom.par ARGUMENT SHOULD HAVE THE NAMES OF THE COMPARTMENT LIST COMING FROM THE par() LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            par(custom.par)
-            text <- c(text, "\nGRAPH PARAMETERS SET TO VALUES DEFINED BY custom.par ARGUMENT\n")
-        }else{
-            par(tempo.par$ini.par)
-            text <- c(text, "\nGRAPH PARAMETERS RESET TO par() DEFAULT VALUES\n")
-        }
-    }
-    output <- list(x.mid.left.dev.region = x.mid.left.dev.region, x.left.dev.region = x.left.dev.region, x.mid.right.dev.region = x.mid.right.dev.region, x.right.dev.region = x.right.dev.region, x.mid.left.fig.region = x.mid.left.fig.region, x.left.fig.region = x.left.fig.region, x.mid.right.fig.region = x.mid.right.fig.region, x.right.fig.region = x.right.fig.region, x.left.plot.region = x.left.plot.region, x.right.plot.region = x.right.plot.region, x.mid.plot.region = x.mid.plot.region, y.mid.bottom.dev.region = y.mid.bottom.dev.region, y.bottom.dev.region = y.bottom.dev.region, y.mid.top.dev.region = y.mid.top.dev.region, y.top.dev.region = y.top.dev.region, y.mid.bottom.fig.region = y.mid.bottom.fig.region, y.bottom.fig.region = y.bottom.fig.region, y.mid.top.fig.region = y.mid.top.fig.region, y.top.fig.region = y.top.fig.region, y.top.plot.region = y.top.plot.region, y.bottom.plot.region = y.bottom.plot.region, y.mid.plot.region = y.mid.plot.region, text = text)
-    return(output)
+# create a fake categ if NULL to deal with legend display
+if(is.null(categ)){
+categ <- vector("list", length(data1))
+categ[] <- "fake_categ"
+for(i2 in 1:length(data1)){
+data1[[i2]] <- cbind(data1[[i2]], fake_categ = "", stringsAsFactors = TRUE)
+if(geom[[i2]] == "geom_hline" | geom[[i2]] == "geom_vline"){
+data1[[i2]][, "fake_categ"] <- factor(paste0("Line_", 1:nrow(data1[[i2]])))
 }
-
-
-######## fun_close() #### close specific graphic windows
-
-
-fun_close <- function(kind = "pdf", return.text = FALSE){
-    # AIM
-    # close only specific graphic windows (devices)
-    # ARGUMENTS:
-    # kind: vector, among c("windows", "quartz", "x11", "X11", "pdf", "bmp", "png", "tiff"), indicating the kind of graphic windows (devices) to close. BEWARE: either "windows", "quartz", "x11" or "X11" means that all the X11 GUI graphics devices will be closed, whatever the OS used
-    # return.text: print text regarding the kind parameter and the devices that were finally closed?
-    # RETURN
-    # text regarding the kind parameter and the devices that were finally closed
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # windows() ; windows() ; pdf() ; dev.list() ; fun_close(kind = c("pdf", "x11"), return.text = TRUE) ; dev.list()
-    # DEBUGGING
-    # kind = c("windows", "pdf") ; return.text = FALSE # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = kind, options = c("windows", "quartz", "x11", "X11", "pdf", "bmp", "png", "tiff"), fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.text, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    text <- paste0("THE REQUIRED KIND OF GRAPHIC DEVICES TO CLOSE ARE ", paste(kind, collapse = " "))
-    if(Sys.info()["sysname"] == "Windows"){ # Note that .Platform$OS.type() only says "unix" for macOS and Linux and "Windows" for Windows
-        if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
-            tempo <- kind %in% c("windows", "quartz", "x11", "X11")
-            kind[tempo] <- "windows" # term are replaced by what is displayed when using a <- dev.list() ; names(a)
-        }
-    }else if(Sys.info()["sysname"] == "Linux"){
-        if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
-            tempo.device <- suppressWarnings(try(X11(), silent = TRUE))[] # open a X11 window to try to recover the X11 system used
-            if( ! is.null(tempo.device)){
-                text <- paste0(text, "\nCANNOT CLOSE GUI GRAPHIC DEVICES AS REQUIRED BECAUSE THIS LINUX SYSTEM DOES NOT HAVE IT")
-            }else{
-                tempo <- kind %in% c("windows", "quartz", "x11", "X11")
-                kind[tempo] <- names(dev.list()[length(dev.list())]) # term are replaced by what is displayed when using a <- dev.list() ; names(a)
-                invisible(dev.off()) # close the X11 opened by tempo
-            }
-        }
-    }else{ # for macOS
-        if(any(kind %in% c("windows", "quartz", "x11", "X11"))){
-            tempo <- kind %in% c("windows", "quartz", "x11", "X11")
-            kind[tempo] <- "quartz" # term are replaced by what is displayed when using a <- dev.list() ; names(a)
-        }
-    }
-    kind <- unique(kind)
-    if(length(dev.list()) != 0){
-        for(i in length(names(dev.list())):1){
-            if(names(dev.list())[i] %in% kind){
-                text <- paste0(text, "\n", names(dev.list())[i], " DEVICE NUMBER ", dev.list()[i], " HAS BEEN CLOSED")
-                invisible(dev.off(dev.list()[i]))
-            }
-        }
-    }
-    if(return.text == TRUE){
-        return(text)
-    }
 }
-
-
-################ Standard graphics
-
-
-######## fun_empty_graph() #### text to display for empty graphs
-
-
-
-
-
-fun_empty_graph <- function(
-    text = NULL, 
-    text.size = 1, 
-    title = NULL, 
-    title.size = 1.5
-){
-    # AIM
-    # display an empty plot with a text in the middle of the window (for instance to specify that no plot can be drawn)
-    # ARGUMENTS
-    # text: character string of the message to display
-    # text.size: numeric value of the text size
-    # title: character string of the graph title
-    # title.size: numeric value of the title size (in points)
-    # RETURN
-    # an empty plot
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # simple example
-    # fun_empty_graph(text = "NO GRAPH")
-    # white page
-    # fun_empty_graph() # white page
-    # all the arguments
-    # fun_empty_graph(text = "NO GRAPH", text.size = 2, title = "GRAPH1", title.size = 1)
-    # DEBUGGING
-    # text = "NO GRAPH" ; title = "GRAPH1" ; text.size = 1
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if( ! is.null(text)){
-        tempo <- fun_check(data = text, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(title)){
-        tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = title.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    ini.par <- par(no.readonly = TRUE) # to recover the initial graphical parameters if required (reset). BEWARE: this command alone opens a pdf of GUI window if no window already opened. But here, protected with the code because always a tempo window opened
-    par(ann=FALSE, xaxt="n", yaxt="n", mar = rep(1, 4), bty = "n", xpd = NA)
-    plot(1, 1, type = "n") # no display with type = "n"
-    x.left.dev.region <- (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / ((par("omd")[2] - par("omd")[1]) * (par("plt")[2] - par("plt")[1]))) * par("omd")[1])
-    y.top.dev.region <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par("omd")[4] - par("omd")[3]) * (par("plt")[4] - par("plt")[3]))) * (1 - par("omd")[4]))
-    if( ! is.null(text)){
-        text(x = 1, y = 1, labels = text, cex = text.size)
-    }
-    if( ! is.null(title)){
-        text(x = x.left.dev.region, y = y.top.dev.region, labels = title, adj=c(0, 1), cex = title.size)
-    }
-    par(ini.par)
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL categ ARGUMENT -> FAKE \"fake_categ\" COLUMN ADDED TO EACH DATA FRAME OF data1, AND FILLED WITH \"\"")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
 }
-
-
-################ gg graphics
-
-
-######## fun_gg_palette() #### ggplot2 default color palette
-
-
-
-
-
-fun_gg_palette <- function(n, kind = "std"){
-    # AIM
-    # provide colors used by ggplot2
-    # the interest is to use another single color that is not the red one used by default
-    # for ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
-    # ARGUMENTS
-    # n: number of groups on the graph
-    # kind: either "std" for standard gg colors, "dark" for darkened gg colors, or "light" for pastel gg colors
-    # RETURN
-    # the vector of hexadecimal colors
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # output of the function
-    # fun_gg_palette(n = 2)
-    # the ggplot2 palette when asking for 7 different colors
-    # plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7))
-    # selection of the 5th color of the ggplot2 palette made of 7 different colors
-    # plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7)[5])
-    # the ggplot2 palette made of 7 darkened colors
-    # plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7, kind = "dark"))
-    # the ggplot2 palette made of 7 lighten colors
-    # plot(1:7, pch = 16, cex = 5, col = fun_gg_palette(n = 7, kind = "light"))
-    # DEBUGGING
-    # n = 0
-    # kind = "std"
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = n, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & isTRUE(all.equal(n, 0))){ # isTRUE(all.equal(n, 0))) is similar to n == 0 but deals with float
-        tempo.cat <- paste0("ERROR IN ", function.name, ": n ARGUMENT MUST BE A NON ZERO INTEGER. HERE IT IS: ", paste(n, collapse = " "))
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-        tempo <- fun_check(data = kind, options = c("std", "dark", "light"), length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    hues = seq(15, 375, length = n + 1)
-    hcl(h = hues, l = if(kind == "std"){65}else if(kind == "dark"){35}else if(kind == "light"){85}, c = 100)[1:n]
+# categ is not NULL anymore
+if(is.null(categ.class.order)){
+categ.class.order <- vector("list", length = length(data1))
+tempo.categ.class.order <- NULL
+for(i2 in 1:length(categ.class.order)){
+categ.class.order[[i2]] <- levels(data1[[i2]][, categ[[i2]]])
+names(categ.class.order)[i2] <- categ[[i2]]
+tempo.categ.class.order <- c(tempo.categ.class.order, ifelse(i2 != 1, "\n", ""), categ.class.order[[i2]])
 }
-
-
-######## fun_gg_just() #### ggplot2 justification of the axis labeling, depending on angle
-
-
-
-
-
-fun_gg_just <- function(angle, pos, kind = "axis"){
-    # AIM
-    # provide correct justification for text labeling, depending on the chosen angle
-    # WARNINGS
-    # justification behave differently on plot, depending whether it is used for annotayed text or for axis labelling. Indeed the latter has labelling constrained
-    # Of note, a bug in ggplot2: vjust sometimes does not work, i.e., the same justification result is obtained whatever the value used. This is the case with angle = 90, pos = "top", kind = "axis". While everything is fine with angle = 90, pos = "bottom", kind = "axis". At least, everything seems fine for kind = "axis" and pos = c("left", "bottom")
-    # ARGUMENTS
-    # angle: integer value of the text angle, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc. 
-    # pos: where text is? Either "top", "right", "bottom" or "left" of the elements to justify from
-    # kind: kind of text? Either "axis" or "text". In the first case, the pos argument refers to the axis position, and in the second to annotated text (using ggplot2::annotate() or ggplot2::geom_text())
-    # RETURN
-    # a list containing:
-    # $angle: the submitted angle (value potentially reduced to fit the [-360 ; 360] interval, e.g., 460 -> 100, without impact on the final angle displayed)
-    # $pos: the selected position (argument pos)
-    # $kind: the selected kind of text (argument kind)
-    # $hjust: the horizontal justification
-    # $vjust: the vertical justification
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_gg_just(angle = 45, pos = "bottom")
-    # fun_gg_just(angle = (360*2 + 45), pos = "left")
-    # output <- fun_gg_just(angle = 45, pos = "bottom") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust))
-    # output <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.y = ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)) + ggplot2::coord_flip()
-    # output1 <- fun_gg_just(angle = 90, pos = "bottom") ; output2 <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; ggplot2::ggplot() + ggplot2::geom_bar(data = obs1, mapping = ggplot2::aes(x = group, y = time), stat = "identity") + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = output1$angle, hjust = output1$hjust, vjust = output1$vjust), axis.text.y = ggplot2::element_text(angle = output2$angle, hjust = output2$hjust, vjust = output2$vjust))
-    # output <- fun_gg_just(angle = -45, pos = "left") ; obs1 <- data.frame(time = 1, km = 1, bird = "pigeon", stringsAsFactors = FALSE) ; ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point() + ggplot2::geom_text(mapping = ggplot2::aes(label = bird), angle = output$angle, hjust = output$hjust, vjust = output$vjust)
-    # obs1 <- data.frame(time = 1:10, km = 1:10, bird = c(NA, NA, NA, "pigeon", NA, "cat", NA, NA, NA, NA), stringsAsFactors = FALSE) ; fun_open(width = 4, height = 4) ; for(i0 in c("text", "axis")){for(i1 in c("top", "right", "bottom", "left")){for(i2 in c(0, 45, 90, 135, 180, 225, 270, 315, 360)){output <- fun_gg_just(angle = i2, pos = i1, kind = i0) ; title <- paste0("kind: ", i0, " | pos: ", i1, " | angle = ", i2, " | hjust: ", output$hjust, " | vjust: ", output$vjust) ; if(i0 == "text"){print(ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point(color = fun_gg_palette(1), alpha = 0.5) + ggplot2::ggtitle(title) + ggplot2::geom_text(mapping = ggplot2::aes(label = bird), angle = output$angle, hjust = output$hjust, vjust = output$vjust) + ggplot2::theme(title = ggplot2::element_text(size = 5)))}else{print(ggplot2::ggplot(data = obs1, mapping = ggplot2::aes(x = time, y = km)) + ggplot2::geom_point(color = fun_gg_palette(1), alpha = 0.5) + ggplot2::ggtitle(title) + ggplot2::geom_text(mapping = ggplot2::aes(label = bird)) + ggplot2::scale_x_continuous(position = ifelse(i1 == "top", "top", "bottom")) + ggplot2::scale_y_continuous(position = ifelse(i1 == "right", "right", "left")) + ggplot2::theme(title = ggplot2::element_text(size = 5), axis.text.x = if(i1 %in% c("top", "bottom")){ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)}, axis.text.y = if(i1 %in% c("right", "left")){ggplot2::element_text(angle = output$angle, hjust = output$hjust, vjust = output$vjust)}))}}}} ; dev.off()
-    # DEBUGGING
-    # angle = 45 ; pos = "left" ; kind = "axis"
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument primary checking
-    # arg with no default values
-    mandat.args <- c(
-        "angle", 
-        "pos"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # using fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = angle, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = pos, options = c("left", "top", "right", "bottom"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = kind, options = c("axis", "text"), length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <- c(
-        "angle", 
-        "pos", 
-        "kind"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # end second round of checking and data preparation
-    # main code
-    # to get angle between -360 and 360
-    while(angle > 360){
-        angle <- angle - 360
-    }
-    while(angle < -360){
-        angle <- angle + 360
-    }
-    # end to get angle between -360 and 360
-    # justifications
-    if(pos %in% c("bottom", "top")){
-        # code below is for if(pos == "bottom"){
-        if(any(sapply(FUN = all.equal, c(-360, -180, 0, 180, 360), angle) == TRUE)){ # equivalent of angle == -360 | angle == -180 | angle == 0 | angle == 180 | angle == 360 but deals with floats
-            hjust <- 0.5
-            if(kind == "text"){
-                if(any(sapply(FUN = all.equal, c(-360, 0, 360), angle) == TRUE)){
-                    vjust <- 1
-                }else if(any(sapply(FUN = all.equal, c(-180, 180), angle) == TRUE)){
-                    vjust <- 0
-                }
-            }else{
-                vjust <- 0.5
-            }
-        }else if(any(sapply(FUN = all.equal, c(-270, 90), angle) == TRUE)){
-            hjust <- 1
-            vjust <- 0.5
-        }else if(any(sapply(FUN = all.equal, c(-90, 270), angle) == TRUE)){
-            hjust <- 0
-            vjust <- 0.5
-        }else if((angle > -360 & angle < -270) | (angle > 0 & angle < 90)){
-            hjust <- 1
-            vjust <- 1
-        }else if((angle > -270 & angle < -180) | (angle > 90 & angle < 180)){
-            hjust <- 1
-            vjust <- 0
-        }else if((angle > -180 & angle < -90) | (angle > 180 & angle < 270)){
-            hjust <- 0
-            vjust <- 0
-            if(kind == "text" & pos == "top"){
-                hjust <- 1
-            }
-        }else if((angle > -90 & angle < 0) | (angle > 270 & angle < 360)){
-            hjust <- 0
-            vjust <- 1
-        }
-        if(pos == "top"){
-            if( ! ((angle > -180 & angle < -90) | (angle > 180 & angle < 270))){
-                hjust <- 1 - hjust
-            }
-            vjust <- 1 - vjust
-        }
-    }else if(pos %in% c("left", "right")){
-        # code below is for if(pos == "left"){
-        if(any(sapply(FUN = all.equal, c(-270, -90, 90, 270), angle) == TRUE)){ # equivalent of angle == -270 | angle == -90 | angle == 90 | angle == 270 but deals with floats
-            hjust <- 0.5
-            if(kind == "text"){
-                if(any(sapply(FUN = all.equal, c(-90, 90), angle) == TRUE)){
-                    vjust <- 0
-                }else if(any(sapply(FUN = all.equal, c(-270, 270), angle) == TRUE)){
-                    vjust <- 1
-                }
-            }else{
-                vjust <- 0.5
-            }
-        }else if(any(sapply(FUN = all.equal, c(-360, 0, 360), angle) == TRUE)){
-            hjust <- 1
-            vjust <- 0.5
-        }else if(any(sapply(FUN = all.equal, c(-180, 180), angle) == TRUE)){
-            hjust <- 0
-            vjust <- 0.5
-        }else if((angle > -360 & angle < -270) | (angle > 0 & angle < 90)){
-            hjust <- 1
-            vjust <- 0
-        }else if((angle > -270 & angle < -180) | (angle > 90 & angle < 180)){
-            hjust <- 0
-            vjust <- 0
-        }else if((angle > -180 & angle < -90) | (angle > 180 & angle < 270)){
-            hjust <- 0
-            vjust <- 1
-        }else if((angle > -90 & angle < 0) | (angle > 270 & angle < 360)){
-            hjust <- 1
-            vjust <- 1
-        }
-        if(pos == "right"){
-            hjust <- 1 - hjust
-            if( ! (((angle > -270 & angle < -180) | (angle > 90 & angle < 180)) | ((angle > -180 & angle < -90) | (angle > 180 & angle < 270)))){
-                vjust <- 1 - vjust
-            }
-        }
-    }
-    # end justifications
-    output <- list(angle = angle, pos = pos, kind = kind, hjust = hjust, vjust = vjust)
-    return(output)
+if(any(unlist(legend.disp))){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") THE categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR CLASS ORDERING:\n", paste(tempo.categ.class.order, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
 }
-
-
-######## fun_gg_get_legend() #### get the legend of ggplot objects
-
-
-
-
-
-fun_gg_get_legend <- function(ggplot_built, fun.name = NULL, lib.path = NULL){
-    # AIM
-    # get legend of ggplot objects
-    # # from https://stackoverflow.com/questions/12539348/ggplot-separate-legend-and-plot
-    # ARGUMENTS
-    # ggplot_built: a ggplot build object
-    # fun.name: single character string indicating the name of the function using fun_gg_get_legend() for warning and error messages. Ignored if NULL
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # RETURN
-    # a list of class c("gtable", "gTree", "grob", "gDesc"), providing legend information of ggplot_built objet, or NULL if the ggplot_built object has no legend
-    # REQUIRED PACKAGES
-    # ggplot2
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # EXAMPLES
-    # Simple example
-    # obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time, fill = group)) ; fun_gg_get_legend(ggplot_built = ggplot2::ggplot_build(p))
-    # Error message because no legend in the ggplot
-    # obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time)) ; fun_gg_get_legend(ggplot_built = ggplot2::ggplot_build(p))
-    # DEBUGGING
-    # obs1 <- data.frame(time = 1:20, group = rep(c("CLASS_1", "CLASS_2"), times = 10), stringsAsFactors = TRUE) ; p <- ggplot2::ggplot() + ggplot2::geom_point(data = obs1, mapping = ggplot2::aes(x = group, y = time)) ; ggplot_built = ggplot2::ggplot_build(p) ; fun.name = NULL ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check",
-        "fun_pack"
-    )
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED ", i1, "() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end required function checking
-    # argument primary checking
-    # arg with no default values
-    mandat.args <- c(
-        "ggplot_built"
-    )
-    tempo <- eval(parse(text = paste0("c(missing(", paste0(mandat.args, collapse = "), missing("), "))")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(sum(tempo, na.rm = TRUE) > 1, "S HAVE", " HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args[tempo], collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # using fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = ggplot_built, class = "ggplot_built", mode = "list", fun.name = function.name) ; eval(ee)
-    if( ! is.null(fun.name)){
-        tempo <- fun_check(data = fun.name, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(arg.check)){
-        if(any(arg.check) == TRUE){
-            stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-        }
-    }
-    # end using fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking
-    # management of NA
-    if(any(is.na(ggplot_built)) | any(is.na(fun.name)) | any(is.na(lib.path))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": NO ARGUMENT CAN HAVE NA VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA
-    # management of NULL
-    if(is.null(ggplot_built)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nggplot_built ARGUMENT CANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL
-    if( ! is.null(lib.path)){
-        if( ! all(dir.exists(lib.path))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end second round of checking
-    # package checking
-    fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
-    # end package checking
-    # main code
-    win.nb <- dev.cur()
-    pdf(file = NULL)
-    tmp <- ggplot2::ggplot_gtable(ggplot_built)
-    # BEWARE with ggplot_gtable : open a blanck device https://stackoverflow.com/questions/17012518/why-does-this-r-ggplot2-code-bring-up-a-blank-display-device
-    invisible(dev.off())
-    if(win.nb > 1){ # to go back to the previous active device, if == 1 means no opened device
-        dev.set(win.nb)
-    }
-    leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
-    if(length(leg) == 0L){
-        legend <- NULL
-    }else{
-        legend <- tmp$grobs[[leg]]
-    }
-    return(legend)
 }
-
-
-######## fun_gg_point_rast() #### ggplot2 raster scatterplot layer
-
-
-
-
-
-fun_gg_point_rast <- function(
-    data = NULL, 
-    mapping = NULL, 
-    stat = "identity", 
-    position = "identity", 
-    ..., 
-    na.rm = FALSE, 
-    show.legend = NA, 
-    inherit.aes = TRUE, 
-    raster.width = NULL, 
-    raster.height = NULL, 
-    raster.dpi = 300, 
-    inactivate = TRUE, 
-    lib.path = NULL
-){
-    # AIM
-    # equivalent to ggplot2::geom_point() but in raster mode
-    # use it like ggplot2::geom_point() with the main raster.dpi additional argument
-    # WARNINGS
-    # can be long to generate the plot
-    # use a square plot region. Otherwise, the dots will have ellipsoid shape
-    # solve the transparency problems with some GUI
-    # this function is derived from the geom_point_rast() function, created by Viktor Petukhov , and present in the ggrastr package (https://rdrr.io/github/VPetukhov/ggrastr/src/R/geom-point-rast.R, MIT License, Copyright (c) 2017 Viktor Petukhov). Has been placed here to minimize package dependencies
-    # ARGUMENTS
-    # classical arguments of geom_point(), shown here https://rdrr.io/github/VPetukhov/ggrastr/man/geom_point_rast.html
-    # raster.width : width of the result image (in inches). Default: deterined by the current device parameters
-    # raster.height: height of the result image (in inches). Default: deterined by the current device parameters
-    # raster.dpi: resolution of the result image
-    # inactivate: logical. Inactivate the fun.name argument of the fun_check() function? If TRUE, the name of the fun_check() function in error messages coming from this function. Use TRUE if fun_gg_point_rast() is used like this: eval(parse(text = "fun_gg_point_rast"))
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # RETURN
-    # a raster scatter plot
-    # REQUIRED PACKAGES
-    # ggplot2
-    # grid (included in the R installation packages but not automatically loaded)
-    # Cairo
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # EXAMPLES
-    # Two pdf in the current directory
-    # set.seed(1) ; data1 = data.frame(x = rnorm(100000), y = rnorm(10000), stringsAsFactors = TRUE) ; fun_open(pdf.name = "Raster") ; ggplot2::ggplot() + fun_gg_point_rast(data = data1, mapping = ggplot2::aes(x = x, y = y)) ; fun_open(pdf.name = "Vectorial") ; ggplot2::ggplot() + ggplot2::geom_point(data = data1, mapping = ggplot2::aes(x = x, y = y)) ; dev.off() ; dev.off()
-    # DEBUGGING
-    # 
-    # function name
-    if(all(inactivate == FALSE)){ # inactivate has to be used here but will be fully checked below
-        function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    }else if(all(inactivate == TRUE)){
-        function.name <- NULL
-    }else{
-        tempo.cat <- paste0("ERROR IN fun_gg_point_rast(): CODE INCONSISTENCY 1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_pack", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if( ! is.null(data)){
-        tempo <- fun_check(data = data, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(mapping)){
-        tempo <- fun_check(data = mapping, class = "uneval", typeof = "list", fun.name = function.name) ; eval(ee) # aes() is tested
-    }
-    # stat and position not tested because too complicate
-    tempo <- fun_check(data = na.rm, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = show.legend, class = "vector", mode = "logical", length = 1, na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = inherit.aes, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(raster.width)){
-        tempo <- fun_check(data = raster.width, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(raster.height)){
-        tempo <- fun_check(data = raster.height, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = raster.dpi, class = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = inactivate, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # package checking
-    fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
-    fun_pack(req.package = c("grid"), lib.path = lib.path)
-    fun_pack(req.package = c("Cairo"), lib.path = lib.path)
-    # end package checking
-    # additional functions
-    DrawGeomPointRast <- function(data, panel_params, coord, na.rm = FALSE, raster.width = NULL, raster.height= NULL, raster.dpi = raster.dpi){
-        if (is.null(raster.width)){
-            raster.width <- par('fin')[1]
-        }
-        if (is.null(raster.height)){
-            raster.height <- par('fin')[2]
-        }
-        prev_dev_id <- dev.cur()
-        p <- ggplot2::GeomPoint$draw_panel(data, panel_params, coord)
-        dev_id <- Cairo::Cairo(type='raster', width = raster.width*raster.dpi, height = raster.height*raster.dpi, dpi = raster.dpi, units = 'px', bg = "transparent")[1]
-        grid::pushViewport(grid::viewport(width = 1, height = 1))
-        grid::grid.points(x = p$x, y = p$y, pch = p$pch, size = p$size,
-                          name = p$name, gp = p$gp, vp = p$vp, draw = T)
-        grid::popViewport()
-        cap <- grid::grid.cap()
-        invisible(dev.off(dev_id))
-        invisible(dev.set(prev_dev_id))
-        grid::rasterGrob(cap, x = 0, y = 0, width = 1, height = 1, default.units = "native", just = c("left","bottom"))
-    }
-    # end additional functions
-    # main code
-    GeomPointRast <- ggplot2::ggproto("GeomPointRast", ggplot2::GeomPoint, draw_panel = DrawGeomPointRast)
-    ggplot2::layer(
-        data = data, 
-        mapping = mapping, 
-        stat = stat, 
-        geom = GeomPointRast, 
-        position = position, 
-        show.legend = show.legend, 
-        inherit.aes = inherit.aes, 
-        params = list(
-            na.rm = na.rm, 
-            raster.width = raster.width, 
-            raster.height = raster.height, 
-            raster.dpi = raster.dpi, 
-            ...
-        )
-    )
-    # end main code
+# end create a fake categ if NULL to deal with legend display
+# categ.class.order is not NULL anymore
+
+
+# vector of color with length as in levels(categ) of data1
+if(is.null(color)){
+color <- vector("list", length(data1))
+length.categ.list <- lapply(lapply(mapply(FUN = "[[", data1, categ, SIMPLIFY = FALSE), FUN = unique), FUN = function(x){length(x[ ! is.na(x)])})
+length.categ.list[sapply(categ, FUN = "==", "fake_categ")] <- 1 # when is.null(color), a single color for all the dots or lines of data[[i1]] that contain "fake_categ" category
+total.categ.length <- sum(unlist(length.categ.list), na.rm = TRUE)
+tempo.color <- fun_gg_palette(total.categ.length)
+tempo.count <- 0
+for(i2 in 1:length(data1)){
+color[[i2]] <- tempo.color[(1:length.categ.list[[i2]]) + tempo.count]
+tempo.count <- tempo.count + length.categ.list[[i2]]
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") NULL color ARGUMENT -> COLORS RESPECTIVELY ATTRIBUTED TO EACH CLASS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i2, " OF categ ARGUMENT")), " (", categ[[i2]], ") IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i2, " OF data1 ARGUMENT")), ":\n", paste(color[[i2]], collapse = " "), "\n", paste(if(all(levels(data1[[i2]][, categ[[i2]]]) == "")){'\"\"'}else{levels(data1[[i2]][, categ[[i2]]])}, collapse = " "))
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
 }
-
-
-######## fun_gg_boxplot() #### ggplot2 boxplot + background dots if required
-
-
-
-
-######## fun_gg_scatter() #### ggplot2 scatterplot + lines (up to 6 overlays totally)
-
-
-
-
-######## fun_gg_heatmap() #### ggplot2 heatmap + overlaid mask if required
-
-
-#test plot.margin = margin(up.space.mds, right.space.mds, down.space.mds, left.space.mds, "inches") to set the dim of the region plot ?
-# if matrix is full of zero (or same value I guess), heatmap is complicate. Test it and error message
-
-fun_gg_heatmap <- function(
-    data1, 
-    legend.name1 = "", 
-    low.color1 = "blue", 
-    mid.color1 = "white", 
-    high.color1 = "red", 
-    limit1 = NULL, 
-    midpoint1 = NULL, 
-    data2 = NULL, 
-    color2 = "black", 
-    alpha2 = 0.5, 
-    invert2 = FALSE, 
-    text.size = 12, 
-    title = "", 
-    title.text.size = 12, 
-    show.scale = TRUE, 
-    rotate = FALSE, 
-    return = FALSE, 
-    plot = TRUE, 
-    add = NULL, 
-    warn.print = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # ggplot2 heatmap with the possibility to overlay a mask
-    # see also:
-    # draw : http://www.sthda.com/english/wiki/ggplot2-quick-correlation-matrix-heatmap-r-software-and-data-visualization
-    # same range scale : https://stackoverflow.com/questions/44655723/r-ggplot2-heatmap-fixed-scale-color-between-graphs 
-    # for ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
-    # ARGUMENTS
-    # data1: numeric matrix or data frame resulting from the conversion of the numeric matrix by reshape2::melt()
-    # legend.name1: character string of the data1 heatmap scale legend
-    # low.color1: character string of the color (i.e., "blue" or "#0000FF") of the lowest scale value
-    # mid.color1: same as low.color1 but for the middle scale value. If NULL, the middle color is the default color between low.color1 and high.color1. BEWARE: argument midpoint1 is not ignored, even if mid.color1 is NULL, meaning that the default mid color can still be controled
-    # high.color1: same as low.color1 but for the highest scale value
-    # limit1: 2 numeric values defining the lowest and higest color scale values. If NULL, take the range of data1 values
-    # midpoint1: single numeric value defining the value corresponding to the mid.color1 argument. A warning message is returned if midpoint1 does not correspond to the mean of limit1 values, because the color scale is not linear anymore. If NULL, takes the mean of limit1 values. Mean of data1, instead of mean of limit1, can be used here if required
-    # data2: binary mask matrix (made of 0 and 1) of same dimension as data1 or a data frame resulting from the conversion of the binary mask matrix by reshape2::melt(). Value 1 of data2 will correspond to color2 argument (value 0 will be NA color), and the opposite if invert2 argument is TRUE (inverted mask)
-    # color2: color of the 1 values of the binary mask matrix. The 0 values will be color NA
-    # alpha2: numeric value (from 0 to 1) of the mask transparency
-    # invert2: logical. Invert the mask (1 -> 0 and 0 -> 1)?
-    # text.size: numeric value of the size of the texts in scale
-    # title: character string of the graph title
-    # title.text.size: numeric value of the title size (in points)
-    # show.scale: logical. Show color scale?
-    # rotate: logical. Rotate the heatmap 90° clockwise?
-    # return: logical. Return the graph parameters?
-    # plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
-    # add: character string allowing to add more ggplot2 features (dots, lines, themes, etc.). BEWARE: (1) must start with "+" just after the simple or double opening quote (no space, end of line, carriage return, etc., allowed), (2) must finish with ")" just before the simple or double closing quote (no space, end of line, carriage return, etc., allowed) and (3) each function must be preceded by "ggplot2::" (for instance: "ggplot2::coord_flip()). If the character string contains the "ggplot2::theme" string, then internal ggplot2 theme() and theme_classic() functions will be inactivated to be reused by add. BEWARE: handle this argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
-    # warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
-    # lib.path: absolute path of the required packages, if not in the default folders
-    # RETURN
-    # a heatmap if plot argument is TRUE
-    # a list of the graph info if return argument is TRUE:
-    # $data: a list of the graphic info
-    # $axes: a list of the axes info
-    # $scale: the scale info (lowest, mid and highest values)
-    # $warn: the warning messages. Use cat() for proper display. NULL if no warning
-    # REQUIRED PACKAGES
-    # ggplot2
-    # reshape2
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # fun_round()
-    # EXAMPLES
-    # fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), title = "GRAPH 1")
-    # fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), return = TRUE)
-    # fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), legend.name1 = "VALUE", title = "GRAPH 1", text.size = 5, data2 = matrix(rep(c(1,0,0,0), 4), ncol = 4), invert2 = FALSE, return = TRUE)
-    # diagonal matrix
-    # fun_gg_heatmap(data1 = matrix(c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1), ncol = 4))
-    # fun_gg_heatmap(data1 = reshape2::melt(matrix(c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1), ncol = 4)))
-    # error message
-    # fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), data2 = matrix(rep(c(1,0,0,0), 5), ncol = 5))
-    # fun_gg_heatmap(data1 = matrix(1:16, ncol = 4), data2 = reshape2::melt(matrix(rep(c(1,0,0,0), 4), ncol = 4)))
-    # fun_gg_heatmap(data1 = reshape2::melt(matrix(1:16, ncol = 4)), data2 = reshape2::melt(matrix(rep(c(1,0,0,0), 4), ncol = 4)))
-    # DEBUGGING
-    # data1 = matrix(1:16, ncol = 4) ; legend.name1 = "" ; low.color1 = "blue" ; mid.color1 = "white" ; high.color1 = "red" ; limit1 = NULL ; midpoint1 = NULL ; data2 = matrix(rep(c(1,0,0,0), 4), ncol = 4) ; color2 = "black" ; alpha2 = 0.5 ; invert2 = FALSE ; text.size = 12 ; title = "" ; title.text.size = 12 ; show.scale = TRUE ; rotate = FALSE ; return = FALSE ; plot = TRUE ; add = NULL ; warn.print = TRUE ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_pack", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_round", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_round() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # no reserved words required for this function
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if(all(is.matrix(data1))){
-        tempo <- fun_check(data = data1, class = "matrix", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }else if(all(is.data.frame(data1))){
-        tempo <- fun_check(data = data1, class = "data.frame", length = 3, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            # structure of reshape2::melt() data frame
-            tempo <- fun_check(data = data1[, 1], data.name = "COLUMN 1 OF data1 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
-            tempo <- fun_check(data = data1[, 2], data.name = "COLUMN 2 OF data1 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
-            tempo <- fun_check(data = data1[, 3], data.name = "COLUMN 3 OF data1 (reshape2::melt() DATA FRAME)", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-        }
-    }else{
-        tempo.cat <- paste0("ERROR IN ", function.name, ": THE data1 ARGUMENT MUST BE A NUMERIC MATRIX OR A DATA FRAME OUTPUT OF THE reshape::melt() FUNCTION")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = legend.name1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = low.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & ! (all(low.color1 %in% colors() | grepl(pattern = "^#", low.color1)))){ # check that all strings of low.color1 start by #
-        tempo.cat <- paste0("ERROR IN ", function.name, ": low.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(mid.color1)){
-        tempo <- fun_check(data = mid.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & ! (all(mid.color1 %in% colors() | grepl(pattern = "^#", mid.color1)))){ # check that all strings of mid.color1 start by #
-            tempo.cat <- paste0("ERROR IN ", function.name, ": mid.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = high.color1, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & ! (all(high.color1 %in% colors() | grepl(pattern = "^#", high.color1)))){ # check that all strings of high.color1 start by #
-        tempo.cat <- paste0("ERROR IN ", function.name, ": high.color1 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(limit1)){
-        tempo <- fun_check(data = limit1, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & any(limit1 %in% c(Inf, -Inf))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": limit1 ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    if( ! is.null(midpoint1)){
-        tempo <- fun_check(data = midpoint1, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(data2)){
-        if(all(is.matrix(data2))){
-            tempo <- fun_check(data = data2, class = "matrix", mode = "numeric", fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE & ! all(unique(data2) %in% c(0,1))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX IN data2 MUST BE MADE OF 0 AND 1 ONLY (MASK MATRIX)")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & all(is.matrix(data1)) & ! identical(dim(data1), dim(data2))){ # matrix and matrix
-                tempo.cat <- paste0("ERROR IN ", function.name, ": MATRIX DIMENSION IN data2 MUST BE IDENTICAL AS MATRIX DIMENSION IN data1. HERE IT IS RESPECTIVELY:\n", paste(dim(data2), collapse = " "), "\n", paste(dim(data1), collapse = " "))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & all(is.data.frame(data1)) & nrow(data1) != prod(dim(data2))){ # reshape2 and matrix
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME IN data2 MUST HAVE ROW NUMBER EQUAL TO PRODUCT OF DIMENSIONS OF data1 MATRIX. HERE IT IS RESPECTIVELY:\n", paste(nrow(data1), collapse = " "), "\n", paste(prod(dim(data2)), collapse = " "))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }else if(all(is.data.frame(data2))){
-            tempo <- fun_check(data = data2, class = "data.frame", length = 3, fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE){
-                # structure of reshape2::melt() data frame
-                tempo <- fun_check(data = data2[, 1], data.name = "COLUMN 1 OF data2 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
-                tempo <- fun_check(data = data2[, 2], data.name = "COLUMN 2 OF data2 (reshape2::melt() DATA FRAME)", typeof = "integer", fun.name = function.name) ; eval(ee)
-                tempo <- fun_check(data = data2[, 3], data.name = "COLUMN 3 OF data2 (reshape2::melt() DATA FRAME)", mode = "numeric", fun.name = function.name) ; eval(ee)
-            }
-            if(tempo$problem == FALSE & ! all(unique(data2[, 3]) %in% c(0,1))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": THIRD COLUMN OF DATA FRAME IN data2 MUST BE MADE OF 0 AND 1 ONLY (MASK DATA FRAME)")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & all(is.data.frame(data1)) & ! identical(dim(data1), dim(data2))){ # data frame and data frame
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME DIMENSION IN data2 MUST BE IDENTICAL TO DATA FRAME DIMENSION IN data1. HERE IT IS RESPECTIVELY:\n", paste(dim(data2), collapse = " "), "\n", paste(dim(data1), collapse = " "))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & all(is.matrix(data1)) & nrow(data2) != prod(dim(data1))){ # reshape2 and matrix
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DATA FRAME IN data2 MUST HAVE ROW NUMBER EQUAL TO PRODUCT OF DIMENSION OF data1 MATRIX. HERE IT IS RESPECTIVELY:\n", paste(nrow(data2), collapse = " "), "\n", paste(prod(dim(data1)), collapse = " "))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE data2 ARGUMENT MUST BE A NUMERIC MATRIX OR A DATA FRAME OUTPUT OF THE reshape::melt() FUNCTION")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = color2, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & ! (all(color2 %in% colors() | grepl(pattern = "^#", color2)))){ # check that all strings of color2 start by #
-        tempo.cat <- paste0("ERROR IN ", function.name, ": color2 ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors()")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = alpha2, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = invert2, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = show.scale, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(add)){
-        tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & ! grepl(pattern = "^\\+", add)){ # check that the add string start by +
-            tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }else if(tempo$problem == FALSE & ! grepl(pattern = "ggplot2::", add)){ #
-            tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST CONTAIN \"ggplot2::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }else if(tempo$problem == FALSE & ! grepl(pattern = ")$", add)){ # check that the add string  finished by )
-            tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # package checking
-    fun_pack(req.package = c("reshape2", "ggplot2"), lib.path = lib.path)
-    # end package checking
-    # main code
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    if(all(is.matrix(data1))){
-        data1 <- reshape2::melt(data1) # transform a matrix into a data frame with 2 coordinates columns and the third intensity column
-    }
-    if(rotate == TRUE){
-        data1[, 1] <- rev(data1[, 1])
-    }
-    if(is.null(limit1)){
-        if(any(data1[, 3] %in% c(Inf, -Inf))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE THIRD COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        limit1 <- range(data1[, 3], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE limit1 ARGUMENT IS NULL -> RANGE OF data1 ARGUMENT HAS BEEN TAKEN: ", paste(fun_round(limit1), collapse = " "))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        if(suppressWarnings(any(limit1 %in% c(Inf, -Inf)))){
-            tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED LIMIT CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(is.null(midpoint1)){
-        midpoint1 <- mean(limit1, na.rm = TRUE)
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE midpoint1 ARGUMENT IS NULL -> MEAN OF limit1 ARGUMENT HAS BEEN TAKEN: ", paste(fun_round(midpoint1), collapse = " "))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }else if(fun_round(midpoint1, 9) != fun_round(mean(limit1), 9)){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE midpoint1 ARGUMENT (", fun_round(mean(midpoint1), 9), ") DOES NOT CORRESPOND TO THE MEAN OF THE limit1 ARGUMENT (", fun_round(mean(limit1), 9), "). COLOR SCALE IS NOT LINEAR")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    if( ! is.null(data2)){
-        if(all(is.matrix(data2))){
-            data2 <- reshape2::melt(data2) # transform a matrix into a data frame with 2 coordinates columns and the third intensity column
-        }
-        if(rotate == TRUE){
-            data2[, 1] <- rev(data2[, 1])
-        }
-        data2[, 3] <- factor(data2[, 3]) # to converte continuous scale into discrete scale
-    }
-    tempo.gg.name <- "gg.indiv.plot."
-    tempo.gg.count <- 0 # to facilitate debugging
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggplot())
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data1, mapping = ggplot2::aes_string(x = names(data1)[ifelse(rotate == FALSE, 2, 1)], y = names(data1)[ifelse(rotate == FALSE, 1, 2)], fill = names(data1)[3]), show.legend = show.scale)) # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_fill_gradient2(low = low.color1, high = high.color1, mid = mid.color1, midpoint = midpoint1, limit = limit1, breaks = c(limit1[1], midpoint1, limit1[2]), labels = fun_round(c(limit1[1], midpoint1, limit1[2])), name = legend.name1))
-    if( ! is.null(data2)){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data2, mapping = ggplot2::aes_string(x = names(data2)[ifelse(rotate == FALSE, 2, 1)], y = names(data2)[ifelse(rotate == FALSE, 1, 2)], alpha = names(data2)[3]), fill = color2, show.legend = FALSE))
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", values = if(invert2 == FALSE){c(0, alpha2)}else{c(alpha2, 0)}, guide = FALSE))
-        # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_raster(data = data2, mapping = ggplot2::aes_string(x = names(data2)[ifelse(rotate == FALSE, 2, 1)], y = names(data2)[ifelse(rotate == FALSE, 1, 2)], group = names(data2)[3]), fill = data2[, 3], alpha = alpha2, show.legend = FALSE)) # BEWARE: this does not work if NA present, because geom_raster() has a tendency to complete empty spaces, and thus, behave differently than geom_tile(). See https://github.com/tidyverse/ggplot2/issues/3025
-    }
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_fixed()) # x = y
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_y_reverse())
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
-    add.check <- TRUE
-    if( ! is.null(add)){ # if add is NULL, then = 0
-        if(grepl(pattern = "ggplot2::theme", add) == TRUE){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT -> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            add.check <- FALSE
-        }
-    }
-    if(add.check == TRUE){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme(
-            text = ggplot2::element_text(size = text.size), 
-            plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-            line = ggplot2::element_blank(),
-            axis.title = ggplot2::element_blank(),
-            axis.text = ggplot2::element_blank(),
-            axis.ticks = ggplot2::element_blank(),
-            panel.background = ggplot2::element_blank()
-        ))
-    }
-    if(plot == TRUE){
-        # suppressWarnings(
-        print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))
-        # )
-    }else{
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    if(return == TRUE){
-        output <- ggplot2::ggplot_build(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "))))
-        output <- output$data
-        names(output)[1] <- "heatmap"
-        if( ! is.null(data2)){
-            names(output)[2] <- "mask"
-        }
-        return(list(data = output, axes = output$layout$panel_params[[1]], scale = c(limit1[1],  midpoint1, limit1[2]), warn = warn))
-    }
 }
-
-
-######## fun_gg_empty_graph() #### text to display for empty graphs
+# end vector of color with length as in levels(categ) of data1
+# color is not NULL anymore
 
 
 
 
 
-fun_gg_empty_graph <- function(
-    text = NULL, 
-    text.size = 12, 
-    title = NULL, 
-    title.size = 8, 
-    lib.path = NULL
-){
-    # AIM
-    # display an empty ggplot2 plot with a text in the middle of the window (for instance to specify that no plot can be drawn)
-    # ARGUMENTS
-    # text: character string of the message to display
-    # text.size: numeric value of the text size (in points)
-    # title: character string of the graph title
-    # title.size: numeric value of the title size (in points)
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL
-    # RETURN
-    # an empty plot
-    # REQUIRED PACKAGES
-    # ggplot2
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # EXAMPLES
-    ### simple example
-    # fun_gg_empty_graph(text = "NO GRAPH")
-    ### white page
-    # fun_gg_empty_graph()
-    ### all the arguments
-    # fun_gg_empty_graph(text = "NO GRAPH", text.size = 8, title = "GRAPH1", title.size = 10, lib.path = NULL)
-    # DEBUGGING
-    # text = "NO GRAPH" ; text.size = 12 ; title = "GRAPH1" ; title.size = 8 ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_pack", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if( ! is.null(text)){
-        tempo <- fun_check(data = text, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(title)){
-        tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = title.size, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # package checking
-    fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
-    # end package checking
-    # main code
-    tempo.gg.name <- "gg.indiv.plot."
-    tempo.gg.count <- 0
-    # no need loop part
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggplot())
-    if( ! is.null(text)){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(data = data.frame(x = 1, y = 1, stringsAsFactors = TRUE), ggplot2::aes(x = x, y = y, label = text), size = text.size))
-    }
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_void())
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-        plot.title = ggplot2::element_text(size = title.size) # stronger than text
-    ))
-    suppressWarnings(print(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))))
+# last check
+for(i1 in 1:length(data1)){
+if(categ[[i1]] != "fake_categ" & length(color[[i1]]) != length(unique(data1[[i1]][, categ[[i1]]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, " LAST CHECK: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE THE LENGTH OF LEVELS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LEVELS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])), "\nREMINDER: A SINGLE COLOR PER CLASS OF CATEG AND A SINGLE CLASS OF CATEG PER COLOR MUST BE RESPECTED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else if(categ[[i1]] == "fake_categ" & length(color[[i1]]) != 1){
+tempo.cat <- paste0("ERROR IN ", function.name, " LAST CHECK: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE LENGTH 1 WHEN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IS NULL\nHERE IT IS COLOR LENGTH ", length(color[[i1]]))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
 }
+}
+# end last check
 
 
-################ Graphic extraction
 
 
-######## fun_trim() #### display values from a quantitative variable and trim according to defined cut-offs
 
-# Add name of the variable in the graph
-# not max and min for boxplot but 1.5IQR
-fun_trim <- function(
-    data, 
-    displayed.nb = NULL, 
-    single.value.display = FALSE, 
-    trim.method = "", 
-    trim.cutoffs = c(0.05, 
-                     0.975), 
-    interval.scale.disp = TRUE, 
-    down.space = 0.75, 
-    left.space = 0.75, 
-    up.space = 0.3, 
-    right.space = 0.25, 
-    orient = 1, 
-    dist.legend = 0.37, 
-    box.type = "l", 
-    amplif.label = 1.25, 
-    amplif.axis = 1.25, 
-    std.x.range = TRUE, 
-    std.y.range = TRUE, 
-    cex.pt = 0.2, 
-    col.box = hsv(0.55, 
-                  0.8, 
-                  0.8), 
-    x.nb.inter.tick = 4, 
-    y.nb.inter.tick = 0, 
-    tick.length = 1, 
-    sec.tick.length = 0.75, 
-    corner.text = "", 
-    amplif.legend = 1, 
-    corner.text.size = 0.75, 
-    trim.return = FALSE
-){
-    # AIM
-    # trim and display values from a numeric vector or matrix
-    # plot 4 graphs: stripchart of values, stripchart of rank of values, histogram and normal QQPlot
-    # different kinds of intervals are displayed on the top of graphes to facilitate the analysis of the variable and a trimming setting
-    # the trimming interval chosen is displayed on top of graphs
-    # both trimmed and not trimmed values are returned in a list
-    # ARGUMENTS
-    # data: values to plot (either a numeric vector or a numeric matrix)
-    # displayed.nb: number of values displayed. If NULL, all the values are displayed. Otherwise, if the number of values is over displayed.nb, then displayed.nb values are displayed after random selection
-    # single.value.display: provide the 4 graphs if data is made of a single (potentially repeated value)? If FALSE, an empty graph is displayed if data is made of a single (potentially repeated value). And the return list is made of NULL compartments
-    # trim.method: Write "" if not required. write "mean.sd" if mean +/- sd has to be displayed as a trimming interval (only recommanded for normal distribution). Write "quantile" to display a trimming interval based on quantile cut-offs. No other possibility allowed. See trim.cutoffs below
-    # trim.cutoffs: 2 values cutoff for the trimming interval displayed, each value between 0 and 1. Not used if trim.method == "".The couple of values c(lower, upper) represents the lower and upper boundaries of the trimming interval (in proportion), which represent the interval of distribution kept (between 0 and 1). Example: trim.cutoffs = c(0.05, 0.975). What is strictly kept for the display is ]lower , upper[, boundaries excluded. Using the "mean.sd" method, 0.025 and 0.975 represent 95% CI which is mean +/- 1.96 * sd
-    # interval.scale.disp: display sd and quantiles intervals on top of graphs ?
-    # down.space: lower vertical margin (in inches, mai argument of par())
-    # left.space: left horizontal margin (in inches, mai argument of par())
-    # up.space: upper vertical margin between plot region and grapical window (in inches, mai argument of par())
-    # right.space: right horizontal margin (in inches, mai argument of par())
-    # orient: scale number orientation (las argument of par()). 0, always parallel to the axis; 1, always horizontal; 2, always perpendicular to the axis; 3, always vertical
-    # dist.legend: numeric value that moves axis legends away in inches (first number of mgp argument of par() but in inches thus / 0.2)
-    # box.type: bty argument of par(). Either "o", "l", "7", "c", "u", "]", the resulting box resembles the corresponding upper case letter. A value of "n" suppresses the box
-    # amplif.label: increase or decrease the size of the text in legends
-    # amplif.axis: increase or decrease the size of the scale numbers in axis
-    # std.x.range: standard range on the x-axis? TRUE (no range extend) or FALSE (4% range extend). Controls xaxs argument of par() (TRUE is xaxs = "i", FALSE is xaxs = "r")
-    # std.y.range: standard range on the y-axis? TRUE (no range extend) or FALSE (4% range extend). Controls yaxs argument of par() (TRUE is yaxs = "i", FALSE is yaxs = "r")
-    # cex.pt: size of points in stripcharts (in inches, thus cex.pt will be thereafter / 0.2)
-    # col.box: color of boxplot
-    # x.nb.inter.tick: number of secondary ticks between main ticks on x-axis (only if not log scale). Zero means non secondary ticks
-    # y.nb.inter.tick: number of secondary ticks between main ticks on y-axis (only if not log scale). Zero means non secondary ticks
-    # tick.length: length of the ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc. 0 means no tick
-    # sec.tick.length: length of the secondary ticks (1 means complete the distance between the plot region and the axis numbers, 0.5 means half the length, etc., 0 for no ticks)
-    # corner.text: text to add at the top right corner of the window
-    # amplif.legend: increase or decrease the size of the text of legend
-    # corner.text.size: positive numeric. Increase or decrease the size of the text. Value 1 does not change it, 0.5 decreases by half, 2 increases by 2
-    # trim.return: return the trimmed and non trimmed values? NULL returned for trimmed and non trimmed values if trim.method == ""
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # RETURN
-    # a list containing:
-    # $trim.method: correspond to trim.method above
-    # $trim.cutoffs: correspond to trim.cutoffs above
-    # $real.trim.cutoffs: the two boundary values (in the unit of the numeric vector or numeric matrix analyzed). NULL 
-    # $trimmed.values: the values outside of the trimming interval as defined in trim.cutoffs above
-    # $kept.values: the values inside the trimming interval as defined in trim.cutoffs above
-    # EXAMPLES
-    # fun_trim(data = c(1:100, 1:10), displayed.nb = NULL, single.value.display = FALSE, trim.method = "mean.sd", trim.cutoffs = c(0.05, 0.975), interval.scale.disp = TRUE, down.space = 0.75, left.space = 0.75, up.space = 0.3, right.space = 0.25, orient = 1, dist.legend = 0.37, box.type = "l", amplif.label = 1.25, amplif.axis = 1.25, std.x.range = TRUE, std.y.range = TRUE, cex.pt = 0.2, col.box = hsv(0.55, 0.8, 0.8), x.nb.inter.tick = 4, y.nb.inter.tick = 0, tick.length = 0.5, sec.tick.length = 0.3, corner.text = "", amplif.legend = 1, corner.text.size = 0.75, trim.return = TRUE)
-    # DEBUGGING
-    # data = c(1:100, 1:10) ; displayed.nb = NULL ; single.value.display = FALSE ; trim.method = "quantile" ; trim.cutoffs = c(0.05, 0.975) ; interval.scale.disp = TRUE ; down.space = 1 ; left.space = 1 ; up.space = 0.5 ; right.space = 0.25 ; orient = 1 ; dist.legend = 0.5 ; box.type = "l" ; amplif.label = 1 ; amplif.axis = 1 ; std.x.range = TRUE ; std.y.range = TRUE ; cex.pt = 0.1 ; col.box = hsv(0.55, 0.8, 0.8) ; x.nb.inter.tick = 4 ; y.nb.inter.tick = 0 ; tick.length = 0.5 ; sec.tick.length = 0.3 ; corner.text = "" ; amplif.legend = 1 ; corner.text.size = 0.75 ; trim.return = TRUE # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    # argument checking without fun_check()
-    if( ! (all(class(data) == "numeric") | all(class(data) == "integer") | (all(class(data) %in% c("matrix", "array")) & base::mode(data) == "numeric"))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data ARGUMENT MUST BE A NUMERIC VECTOR OR NUMERIC MATRIX")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking without fun_check()
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    if( ! is.null(displayed.nb)){
-        tempo <- fun_check(data = displayed.nb, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-        if(displayed.nb < 2){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": displayed.nb ARGUMENT MUST BE A SINGLE INTEGER VALUE GREATER THAN 1 AND NOT: ", paste(displayed.nb, collapse = " "))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = single.value.display, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = trim.method, options = c("", "mean.sd", "quantile"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = trim.cutoffs, class = "vector", mode = "numeric", length = 2, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = interval.scale.disp, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = down.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = left.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = up.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = right.space, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = orient, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dist.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.type, options = c("o", "l", "7", "c", "u", "]", "n"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = amplif.label, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = amplif.axis, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = std.x.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = std.y.range, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = cex.pt, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = col.box, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.nb.inter.tick, class = "integer", length = 1, neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.nb.inter.tick, class = "integer", length = 1, neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = sec.tick.length, class = "vector", mode = "numeric", length = 1, prop = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = corner.text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = amplif.legend, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = corner.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = trim.return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    if(all(is.na(data) | ! is.finite(data))){
-        tempo.cat <- paste0("ERROR IN fun_trim FUNCTION\ndata ARGUMENT CONTAINS ONLY NA OR Inf")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end argument checking
-    # main code
-    if(all(class(data)%in% c("matrix", "array"))){
-        data <- as.vector(data)
-    }
-    na.nb <- NULL
-    if(any(is.na(data))){
-        na.nb <- sum(c(is.na(data)))
-        data <- data[ ! is.na(data)]
-    }
-    color.cut <- hsv(0.75, 1, 1) # color of interval selected
-    col.mean <- hsv(0.25, 1, 0.8) # color of interval using mean+/-sd
-    col.quantile <- "orange" # color of interval using quantiles
-    quantiles.selection <- c(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.975, 0.99) # quantiles used in axis to help for choosing trimming cutoffs
-    if(single.value.display == FALSE & length(unique(data)) == 1L){
-        par(bty = "n", xaxt = "n", yaxt = "n", xpd = TRUE)
-        plot(1, pch = 16, col = "white", xlab = "", ylab = "")
-        text(x = 1, y = 1, paste0("No graphic displayed\nBecause data made of a single different value (", formatC(as.double(table(data))), ")"), cex = 2)
-        output <- list(trim.method = NULL, trim.cutoffs = NULL, real.trim.cutoffs = NULL, trimmed.values = NULL, kept.values = NULL)
-    }else{
-        output <- list(trim.method = trim.method, trim.cutoffs = trim.cutoffs, real.trim.cutoffs = NULL, trimmed.values = NULL, kept.values = NULL)
-        fun.rug <- function(sec.tick.length.f = sec.tick.length, x.nb.inter.tick.f = x.nb.inter.tick, y.nb.inter.tick.f = y.nb.inter.tick){
-            if(x.nb.inter.tick.f > 0){
-                inter.tick.unit <- (par("xaxp")[2] - par("xaxp")[1]) / par("xaxp")[3]
-                par.ini <- par()[c("xpd", "tcl")]
-                par(xpd = FALSE)
-                par(tcl = -par()$mgp[2] * sec.tick.length.f) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
-                suppressWarnings(rug(seq(par("xaxp")[1] - 10 * inter.tick.unit, par("xaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + x.nb.inter.tick.f)), ticksize = NA, side = 1)) # ticksize = NA to allow the use of par()$tcl value
-                par(par.ini)
-                rm(par.ini)
-            }
-            if(y.nb.inter.tick.f > 0){
-                inter.tick.unit <- (par("yaxp")[2] - par("yaxp")[1]) / par("yaxp")[3]
-                par.ini <- par()[c("xpd", "tcl")]
-                par(xpd = FALSE)
-                par(tcl = -par()$mgp[2] * sec.tick.length.f) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
-                suppressWarnings(rug(seq(par("yaxp")[1] - 10 * inter.tick.unit, par("yaxp")[2] + 10 * inter.tick.unit, by = inter.tick.unit / (1 + y.nb.inter.tick.f)), ticksize = NA, side = 2)) # ticksize = NA to allow the use of par()$tcl value
-                par(par.ini)
-                rm(par.ini)
-            }
-        }
-        fun.add.cut <- function(data.f, trim.method.f = trim.method, trim.cutoffs.f = trim.cutoffs, color.cut.f = color.cut, return.f = FALSE){
-            # DEBUGGING
-            # data.f = data ; trim.method.f = "mean.sd"; trim.cutoffs.f = trim.cutoffs ; color.cut.f = color.cut ; return.f = TRUE
-            real.trim.cutoffs.f <- NULL
-            if(trim.method.f != ""){
-                data.f <- sort(data.f)
-                par.ini <- par()$xpd
-                par(xpd = FALSE)
-                if(trim.method.f == "mean.sd"){
-                    real.trim.cutoffs.f <- qnorm(trim.cutoffs.f, mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE))
-                    abline(v = qnorm(trim.cutoffs.f, mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), col = color.cut.f)
-                    segments(qnorm(trim.cutoffs.f[1], mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), par()$usr[4] * 0.75, qnorm(trim.cutoffs.f[2], mean(data.f, na.rm = TRUE), sd(data.f, na.rm = TRUE)), par()$usr[4] * 0.75, col = color.cut.f)
-                }
-                if(trim.method.f == "quantile"){
-                    real.trim.cutoffs.f <- quantile(data.f, probs = trim.cutoffs.f, type = 7, na.rm = TRUE)
-                    abline(v = quantile(data.f, probs = trim.cutoffs.f, type = 7, na.rm = TRUE), col = color.cut.f)
-                    segments(quantile(data.f, probs = trim.cutoffs.f[1], type = 7, na.rm = TRUE), par()$usr[4] * 0.75, quantile(data.f, probs = trim.cutoffs.f[2], type = 7, na.rm = TRUE), par()$usr[4] * 0.75, col = color.cut.f)
-                }
-                par(par.ini)
-                if(return.f == TRUE){
-                    trimmed.values.f <- data.f[data.f <= real.trim.cutoffs.f[1] | data.f >= real.trim.cutoffs.f[2]]
-                    kept.values.f <- data.f[data.f > real.trim.cutoffs.f[1] & data.f < real.trim.cutoffs.f[2]]
-                }
-            }else{
-                real.trim.cutoffs.f <- NULL
-                trimmed.values.f <- NULL
-                kept.values.f <- NULL
-            }
-            if(return.f == TRUE){
-                output <- list(trim.method = trim.method.f, trim.cutoffs = trim.cutoffs.f, real.trim.cutoffs = real.trim.cutoffs.f, trimmed.values = trimmed.values.f, kept.values = kept.values.f)
-                return(output)
-            }
-        }
-        fun.interval.scale.display <- function(data.f, col.quantile.f = col.quantile, quantiles.selection.f = quantiles.selection, col.mean.f = col.mean){ # intervals on top of graphs
-            par.ini <- par()[c("mgp", "xpd")]
-            par(mgp = c(0.25, 0.25, 0), xpd = NA)
-            axis(side = 3, at = c(par()$usr[1], par()$usr[2]), labels = rep("", 2), col = col.quantile.f, lwd.ticks = 0)
-            par(xpd = FALSE)
-            axis(side = 3, at = quantile(as.vector(data.f), probs = quantiles.selection.f, type = 7, na.rm = TRUE), labels = quantiles.selection.f, col.axis = col.quantile.f, col = col.quantile.f)
-            par(mgp = c(1.75, 1.75, 1.5), xpd = NA)
-            axis(side = 3, at = c(par()$usr[1], par()$usr[2]), labels = rep("", 2), col = col.mean.f, lwd.ticks = 0)
-            par(xpd = FALSE)
-            axis(side = 3, at = m + s * qnorm(quantiles.selection.f), labels = formatC(round(qnorm(quantiles.selection.f), 2)), col.axis = col.mean.f, col = col.mean.f, lwd.ticks = 1)
-            par(par.ini)
-        }
-        zone<-matrix(1:4, ncol=2)
-        layout(zone)
-        par(omi = c(0, 0, 1.5, 0), mai = c(down.space, left.space, up.space, right.space), las = orient, mgp = c(dist.legend / 0.2, 0.5, 0), xpd = FALSE, bty= box.type, cex.lab = amplif.label, cex.axis = amplif.axis, xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
-        par(tcl = -par()$mgp[2] * tick.length) # tcl gives the length of the ticks as proportion of line text, knowing that mgp is in text lines. So the main ticks are a 0.5 of the distance of the axis numbers by default. The sign provides the side of the tick (negative for outside of the plot region)
-        if(is.null(displayed.nb)){
-            sampled.data <- as.vector(data)
-            if(corner.text == ""){
-                corner.text <- paste0("ALL VALUES OF THE DATASET DISPLAYED")
-            }else{
-                corner.text <- paste0(corner.text, "\nALL VALUES OF THE DATASET DISPLAYED")
-            }
-        }else{
-            if(length(as.vector(data)) > displayed.nb){
-                sampled.data <- sample(as.vector(data), displayed.nb, replace = FALSE)
-                if(corner.text == ""){
-                    corner.text <- paste0("WARNING: ONLY ", displayed.nb, " VALUES ARE DISPLAYED AMONG THE ", length(as.vector(data)), " VALUES OF THE DATASET ANALYZED")
-                }else{
-                    corner.text <- paste0(corner.text, "\nWARNING: ONLY ", displayed.nb, " VALUES ARE DISPLAYED AMONG THE ", length(as.vector(data)), " VALUES OF THE DATASET ANALYZED")
-                }
-            }else{
-                sampled.data <- as.vector(data)
-                if(corner.text == ""){
-                    corner.text <- paste0("WARNING: THE DISPLAYED NUMBER OF VALUES PARAMETER ", deparse(substitute(displayed.nb)), " HAS BEEN SET TO ", displayed.nb, " WHICH IS ABOVE THE NUMBER OF VALUES OF THE DATASET ANALYZED -> ALL VALUES DISPLAYED")
-                }else{
-                    corner.text <- paste0(corner.text, "\nWARNING: THE DISPLAYED NUMBER OF VALUES PARAMETER ", deparse(substitute(displayed.nb)), " HAS BEEN SET TO ", displayed.nb, " WHICH IS ABOVE THE NUMBER OF VALUES OF THE DATASET ANALYZED -> ALL VALUES DISPLAYED")
-                }
-            }
-        }
-        if( ! is.null(na.nb)){
-            if(corner.text == ""){
-                corner.text <- paste0("WARNING: NUMBER OF NA REMOVED IS ", na.nb)
-            }else{
-                corner.text <- paste0("WARNING: NUMBER OF NA REMOVED IS ", na.nb)
-            }
-        }
-        stripchart(sampled.data, method="jitter", jitter=0.4, vertical=FALSE, ylim=c(0.5, 1.5), group.names = "", xlab = "Value", ylab="", pch=1, cex = cex.pt / 0.2)
-        fun.rug(y.nb.inter.tick.f = 0)
-        boxplot(as.vector(data), horizontal=TRUE, add=TRUE, boxwex = 0.4, staplecol = col.box, whiskcol = col.box, medcol = col.box, boxcol = col.box, range = 0, whisklty = 1)
-        m <- mean(as.vector(data), na.rm = TRUE)
-        s <- sd(as.vector(data), na.rm = TRUE)
-        segments(m, 0.8, m, 1, lwd=2, col="red") # mean 
-        segments(m -1.96 * s, 0.9, m + 1.96 * s, 0.9, lwd=1, col="red") # mean 
-        graph.xlim <- par()$usr[1:2] # for hist() and qqnorm() below
-        if(interval.scale.disp == TRUE){
-            fun.interval.scale.display(data.f = data)
-            if(corner.text == ""){
-                corner.text <- paste0("MULTIPLYING FACTOR DISPLAYED (MEAN +/- SD) ON SCALES: ", paste(formatC(round(qnorm(quantiles.selection), 2))[-(1:(length(quantiles.selection) - 1) / 2)], collapse = ", "), "\nQUANTILES DISPLAYED ON SCALES: ", paste(quantiles.selection, collapse = ", "))
-            }else{
-                corner.text <- paste0(corner.text, "\nMULTIPLYING FACTOR DISPLAYED (MEAN +/- SD) ON SCALES: ", paste(formatC(round(qnorm(quantiles.selection), 2))[-(1:(length(quantiles.selection) - 1) / 2)], collapse = ", "), "\nQUANTILES DISPLAYED ON SCALES: ", paste(quantiles.selection, collapse = ", "))
-            }
-        }
-        output.tempo <- fun.add.cut(data.f = data, return.f = TRUE) # to recover real.trim.cutoffs
-        if(trim.return == TRUE){
-            output <- output.tempo
-        }
-        par(xpd = NA)
-        if(trim.method != ""){
-            if(corner.text == ""){
-                corner.text <- paste0("SELECTED CUT-OFFS (PROPORTION): ", paste(trim.cutoffs, collapse = ", "), "\nSELECTED CUT-OFFS: ", paste(output.tempo$real.trim.cutoffs, collapse = ", "))
-            }else{
-                corner.text <- paste0(corner.text, "\nSELECTED CUT-OFFS (PROPORTION): ", paste(trim.cutoffs, collapse = ", "), "\nSELECTED CUT-OFFS: ", paste(output.tempo$real.trim.cutoffs, collapse = ", "))
-            }
-            if(interval.scale.disp == TRUE){
-                legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- 1.96sd", paste0("Trimming interval: ", paste0(trim.cutoffs, collapse = " , ")), "Mean +/- sd multiplying factor", "Quantile"), yjust = 0, lty=1, col=c(col.box, "red", color.cut, col.mean, col.quantile), bty="n", cex = amplif.legend)
-            }else{
-                legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- 1.96sd", paste0("Trimming interval: ", paste0(trim.cutoffs, collapse = " , "))), yjust = 0, lty=1, col=c(col.box, "red", color.cut), bty="n", cex = amplif.legend, y.intersp=1.25)
-            }
-        }else{
-            if(interval.scale.disp == TRUE){
-                legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- sd", "Mean +/- sd multiplying factor", "Quantile"), yjust = 0, lty=1, col=c(col.box, "red", col.mean, col.quantile), bty="n", cex = amplif.legend)
-            }else{
-                legend(x = (par("usr")[1] - ((par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1])) * par("plt")[1] - ((par("usr")[2] - par("usr")[1]) / (par("omd")[2] - par("omd")[1])) * par("omd")[1]), y = (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / (par("omd")[4] - par("omd")[3])) * (1 - par("omd")[4]) / 2), legend = c(c("min, Q1, Median, Q3, max"), "mean +/- sd"), yjust = 0, lty=1, col=c(col.box, "red"), bty="n", cex = amplif.legend, y.intersp=1.25)
-            }
-        }
-        par(xpd = FALSE, xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
-        hist(as.vector(data), main = "", xlim = graph.xlim, xlab = "Value", ylab="Density", col = grey(0.25)) # removed: breaks = seq(min(as.vector(data), na.rm = TRUE), max(as.vector(data), na.rm = TRUE), length.out = length(as.vector(data)) / 10)
-        abline(h = par()$usr[3])
-        fun.rug()
-        if(interval.scale.disp == TRUE){
-            fun.interval.scale.display(data.f = data)
-        }
-        fun.add.cut(data.f = data)
-        par(xaxs = ifelse(std.x.range, "i", "r"))
-        stripchart(rank(sampled.data), method="stack", vertical=FALSE, ylim=c(0.99, 1.3), group.names = "", xlab = "Rank of values", ylab="", pch=1, cex = cex.pt / 0.2)
-        fun.rug(y.nb.inter.tick.f = 0)
-        x.text <- par("usr")[2] + (par("usr")[2] - par("usr")[1]) / (par("plt")[2] - par("plt")[1]) * (1 - par("plt")[2]) / 2
-        y.text <- (par("usr")[4] + ((par("usr")[4] - par("usr")[3]) / (par("plt")[4] - par("plt")[3])) * (1 - par("plt")[4]) + ((par("usr")[4] - par("usr")[3]) / ((par()$omd[4] / 2) * ((par("plt")[4] - par("plt")[3])))) * (1 - par("omd")[4])) # BEWARE. Here in "(par()$omd[4] / 2", division by two because there are 2 graphs staked on the y axis, and not one
-        par(xpd=NA)
-        text(x = x.text, y = y.text, paste0(corner.text), adj=c(1, 1.1), cex = corner.text.size) # text at the topright corner
-        par(xpd=FALSE)
-        par(xaxs = ifelse(std.x.range, "i", "r"), yaxs = ifelse(std.y.range, "i", "r"))
-        qqnorm(as.vector(sampled.data), main = "", datax = TRUE, ylab = "Value", pch = 1, col = "red", cex = cex.pt / 0.2)
-        fun.rug()
-        if(diff(quantile(as.vector(data), probs = c(0.25, 0.75), na.rm = TRUE)) != 0){ # otherwise, error generated
-            qqline(as.vector(data), datax = TRUE)
-        }
-        if(interval.scale.disp == TRUE){
-            fun.interval.scale.display(data.f = data)
-        }
-        fun.add.cut(data.f = data)
-    }
-    if(trim.return == TRUE){
-        return(output)
-    }
+# conversion of geom_hline and geom_vline
+for(i1 in 1:length(data1)){
+if(geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline"){
+final.data.frame <- data.frame()
+for(i3 in 1:nrow(data1[[i1]])){
+tempo.data.frame <- rbind(data1[[i1]][i3, ], data1[[i1]][i3, ], stringsAsFactors = TRUE)
+if(geom[[i1]] == "geom_hline"){
+tempo.data.frame[, x[[i1]]] <- x.lim
+}else if(geom[[i1]] == "geom_vline"){
+tempo.data.frame[, y[[i1]]] <- y.lim
+}else{
+tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
 }
-
-
-######## fun_segmentation() #### segment a dot cloud on a scatterplot and define the dots from another cloud outside the segmentation
-
-
-fun_segmentation <- function(
-    data1, 
-    x1, 
-    y1, 
-    x.range.split = NULL, 
-    x.step.factor = 10, 
-    y.range.split = NULL, 
-    y.step.factor = 10, 
-    error = 0, 
-    data2 = NULL, 
-    x2, 
-    y2, 
-    data2.pb.dot = "unknown", 
-    xy.cross.kind = "&", 
-    plot = FALSE, 
-    graph.in.file = FALSE, 
-    raster = TRUE, 
-    warn.print = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # if data1 is a data frame corresponding to the data set of a scatterplot (with a x column for x-axis values and a y column for the y-axis column), then fun_segmentation() delimits a frame around the dots cloud using a sliding window set by x.range.split and x.step.factor to frame the top and bottom part of the cloud, and set by y.range.split and y.step.factor to frame the left and right part of the cloud
-    # if a second data frame is provided, corresponding to the data set of a scatterplot (with a x column for x-axis values and a y column for the y-axis column), then fun_segmentation() defines the dots of this data frame, outside of the frame of the first data frame
-    # WARNINGS
-    # if dots from data2 look significant on the graph (outside the frame) but are not (not black on the last figure), this is probably because the frame is flat on the zero coordinate (no volume inside the frame at this position). Thus, no way to conclude that data2 dots here are significant. These dots are refered to as "unknown". The pb.dot argument deals with such dots
-    # dots that are sometimes inside and outside the frame, depending on the sliding window, are treated differently: they are removed. Such dots are neither classified as "signif", "non signif" or "unknown", but as "inconsistent"
-    # unknown dots are treated as finally significant, not significant, or unknown (data2.pb.dot argument) for each x-axis and y-axis separately. Then, the union or intersection of significant dots is performed (argument xy.cross.kind). See the example section
-    # ARGUMENTS
-    # data1: a data frame containing a column of x-axis values and a column of y-axis values
-    # x1: character string of the data1 column name for x-axis (first column of data1 by default)
-    # y1: character string of the data1 column name for y-axis (second column of data1 by default)
-    # x.range.split: positive non null numeric value giving the number of interval on the x value range. if x.range is the range of the dots on the x-axis, then abs(diff(x.range) / x.range.split) gives the window size. Window size decreases when range.split increases. In unit of x-axis. Write NULL if not required. At least one of the x.range.split and y.range.split must be non NULL
-    # x.step.factor: positive non null numeric value giving the shift step of the window. If x.step.factor = 1, no overlap during the sliding (when the window slides from position n to position n+1, no overlap between the two positions). If x.step.factor = 2, 50% of overlap (when the window slides from position n to position n+1, the window on position n+1 overlap 50% of the window when it was on position n)
-    # y.range.split: same as x.range.split for the y-axis. At least one of the x.range.split and y.range.split must be non NULL
-    # y.step.factor: same as x.step.factor for the y-axis
-    # error: proportion (from 0 to 1) of false positives (i.e., proportion of dots from data1 outside of the frame). 0.05 means 5% of the dots from data1 outside of the frame
-    # data2: a data frame containing a column of x-axis values and a column of y-axis values, for which outside dots of the data1 cloud has to be determined. Write NULL if not required
-    # x2: character string of the data1 column name for x-axis (first column of data1 by default)
-    # y2: character string of the data1 column name for y-axis (second column of data1 by default)
-    # data2.pb.dot: unknown dots are explain in the warning section above. If "signif", then the unknown dots are finally considered as significant (outside the frame). If "not.signif", then the unknown dots are finally considered as non significant (inside the frame). If "unknown", no conclusion are drawn from these dots. See the examples below
-    # xy.cross.kind: if data2 is non null and if both x.range.split and y.range.split are non null, which dots are finally significants? Write "&" for intersection of outside dots on x and on y. Write "|" for union of outside dots on x and on y. See the examples below
-    # plot: logical. Print graphs that check the frame?
-    # graph.in.file: logical. Graphs sent into a graphic device already opened? If FALSE, GUI are opened for each graph. If TRUE, no GUI are opended. The graphs are displayed on the current active graphic device. Ignored if plot is FALSE
-    # raster: logical. Dots in raster mode? If FALSE, dots from each geom_point from geom argument are in vectorial mode (bigger pdf and long to display if millions of dots). If TRUE, dots from each geom_point from geom argument are in matricial mode (smaller pdf and easy display if millions of dots, but long to generate the layer). If TRUE, the region plot will be square to avoid a bug in fun_gg_point_rast(). If TRUE, solve the transparency problem with some GUI. Not considered if plot is FALSE
-    # warn.print: logical. Print warnings at the end of the execution? No print if no warning messages
-    # lib.path: character vector specifying the absolute pathways of the directories containing the required packages if not in the default directories. Ignored if NULL. Ignored if plot is FALSE
-    # RETURN
-    # several graphs if plot is TRUE
-    # a list containing:
-    # $data1.removed.row.nb: which rows have been removed due to NA; NaN, -Inf or Inf detection in x1 or y1 columns (NULL if no row removed)
-    # $data1.removed.rows: removed rows (NULL if no row removed)
-    # $data2.removed.row.nb: which rows have been removed due to NA; NaN, -Inf or Inf detection in x2 or y2 columns (NULL if no row removed)
-    # $data2.removed.rows: removed rows (NULL if no row removed)
-    # $hframe: x and y coordinates of the bottom and top frames for frame plotting (frame1 for the left step and frame2 for the right step)
-    # $vframe: x and y coordinates of the left and right frames for frame plotting (frame1 for the down step and frame2 for the top step)
-    # $data1.signif.dot: the significant dots of data1 (i.e., dots outside the frame). A good segmentation should not have any data1.signif.dot
-    # $data1.non.signif.dot: the non significant dots of data1 (i.e., dots inside the frame)
-    # $data1.inconsistent.dot: see the warning section above
-    # $data2.signif.dot: the significant dots of data2 if non NULL (i.e., dots outside the frame)
-    # $data2.non.signif.dot: the non significant dots of data2 (i.e., dots inside the frame)
-    # $data2.unknown.dot: the problematic dots of data2 (i.e., data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots). Is systematically NULL except if argument data2.pb.dot = "unknown" and some data2 dots are in such situation. Modifying the segmentation x.range.split, x.step.factor, y.range.split, y.step.factor arguments can solve this problem
-    # $data2.inconsistent.dot: see the warning section above
-    # $axes: the x-axis and y-axis info
-    # $warn: the warning messages. Use cat() for proper display. NULL if no warning
-    # REQUIRED PACKAGES
-    # ggplot2 if plot is TRUE
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # if plot is TRUE:
-    # fun_pack()
-    # fun_open()
-    # fun_gg_palette()
-    # fun_gg_scatter()
-    # fun_gg_empty_graph()
-    # fun_close()
-    # EXAMPLES
-    # example explaining the unknown and inconsistent dots, and the cross 
-    
-    # set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data1[5:7, 2] <- NA ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; data2[11:13, 1] <- Inf ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = 20, x.step.factor = 10, y.range.split = 23, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "not.signif", xy.cross.kind = "|", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
-    # set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = NULL, x.step.factor = 10, y.range.split = 23, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "unknown", xy.cross.kind = "|", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
-    # set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_segmentation(data1 = data1, x1 = names(data1)[1], y1 = names(data1)[2], x.range.split = 20, x.step.factor = 10, y.range.split = NULL, y.step.factor = 10, error = 0, data2 = data2, x2 = names(data2)[1], y2 = names(data2)[2], data2.pb.dot = "unknown", xy.cross.kind = "&", plot = TRUE, graph.in.file = FALSE, raster = FALSE, lib.path = NULL)
-    # DEBUGGING
-    # set.seed(1) ; data1 = data.frame(x = rnorm(50), y = rnorm(50), stringsAsFactors = TRUE) ; data1[5:7, 2] <- NA ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 5 ; x.step.factor = 10 ; y.range.split = 5 ; y.step.factor = 10 ; error = 0 ; data2 = data.frame(x = rnorm(50, 0, 2), y = rnorm(50, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "unknown" ; xy.cross.kind = "|" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
-    # set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 20 ; x.step.factor = 10 ; y.range.split = 23 ; y.step.factor = 10 ; error = 0 ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "not.signif" ; xy.cross.kind = "|" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
-    # set.seed(1) ; data1 = data.frame(x = rnorm(500), y = rnorm(500), stringsAsFactors = TRUE) ; data2 = data.frame(x = rnorm(500, 0, 2), y = rnorm(500, 0, 2), stringsAsFactors = TRUE) ; set.seed(NULL) ; x1 = names(data1)[1] ; y1 = names(data1)[2] ; x.range.split = 20 ; x.step.factor = 10 ; y.range.split = NULL ; y.step.factor = 10 ; error = 0 ; x2 = names(data2)[1] ; y2 = names(data2)[2] ; data2.pb.dot = "unknown" ; xy.cross.kind = "&" ; plot = TRUE ; graph.in.file = FALSE ; raster = FALSE ; warn.print = TRUE ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    ini.warning.length <- options()$warning.length
-    warn <- NULL
-    warn.count <- 0
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & length(data1) < 2){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OF AT LEAST 2 COLUMNS")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = x1, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & ! (x1 %in% names(data1))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": x1 ARGUMENT MUST BE A COLUMN NAME OF data1")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }else if(tempo$problem == FALSE & x1 %in% names(data1)){
-        tempo <- fun_check(data = data1[, x1], data.name = "x1 COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = y1, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & ! (y1 %in% names(data1))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": y1 ARGUMENT MUST BE A COLUMN NAME OF data1")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }else if(tempo$problem == FALSE & y1 %in% names(data1)){
-        tempo <- fun_check(data = data1[, y1], data.name = "y1 COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    }
-    if(is.null(x.range.split) & is.null(y.range.split)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE OF THE x.range.split AND y.range.split ARGUMENTS MUST BE NON NULL")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(x.range.split)){
-        tempo <- fun_check(data = x.range.split, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & x.range.split < 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x.range.split ARGUMENT CANNOT BE LOWER THAN 1")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    if( ! is.null(y.range.split)){
-        tempo <- fun_check(data = y.range.split, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & y.range.split < 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y.range.split ARGUMENT CANNOT BE LOWER THAN 1")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = x.step.factor, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & x.step.factor < 1){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": x.step.factor ARGUMENT CANNOT BE LOWER THAN 1")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = y.step.factor, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & y.step.factor < 1){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": y.step.factor ARGUMENT CANNOT BE LOWER THAN 1")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = error, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(data2)){
-        if(is.null(x2) | is.null(y2)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x2 AND y2 ARGUMENTS CANNOT BE NULL IF data2 ARGUMENT IS NON NULL")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-        tempo <- fun_check(data = data2, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & length(data2) < 2){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": data2 ARGUMENT MUST BE A DATA FRAME OF AT LEAST 2 COLUMNS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-        if( ! is.null(x2)){
-            tempo <- fun_check(data = x2, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE & ! (x2 %in% names(data2))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": x2 ARGUMENT MUST BE A COLUMN NAME OF data2")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & x2 %in% names(data2)){
-                tempo <- fun_check(data = data2[, x2], data.name = "x2 COLUMN OF data2", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-            }
-        }
-        if( ! is.null(y2)){
-            tempo <- fun_check(data = y2, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE & ! (y2 %in% names(data2))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": y2 ARGUMENT MUST BE A COLUMN NAME OF data2")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(tempo$problem == FALSE & y2 %in% names(data2)){
-                tempo <- fun_check(data = data2[, y2], data.name = "y2 COLUMN OF data2", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-            }
-        }
-    }
-    if( ! is.null(data2)){
-        tempo <- fun_check(data = data2.pb.dot, options = c("signif", "not.signif", "unknown"), length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if( ! (is.null(x.range.split)) & ! (is.null(y.range.split))){
-        tempo <- fun_check(data = xy.cross.kind, options = c("&", "|"), length = 1, fun.name = function.name) ; eval(ee)
-    }
-    tempo <- fun_check(data = plot, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & plot == TRUE){
-        tempo <- fun_check(data = raster, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-        tempo <- fun_check(data = graph.in.file, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & graph.in.file == TRUE & is.null(dev.list())){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": \ngraph.in.file PARAMETER SET TO TRUE BUT NO ACTIVE GRAPHIC DEVICE DETECTED")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }else if(tempo$problem == FALSE & graph.in.file == TRUE & ! is.null(dev.list())){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") GRAPHS PRINTED IN THE CURRENT DEVICE (TYPE ", toupper(names(dev.cur())), ")")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        if( ! is.null(lib.path)){
-            tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-            if(tempo$problem == FALSE){
-                if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                    text.check <- c(text.check, tempo.cat)
-                    arg.check <- c(arg.check, TRUE)
-                }
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # other required function checking
-    if(plot == TRUE){
-        if(length(utils::find("fun_pack", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(utils::find("fun_open", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_open() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(utils::find("fun_gg_palette", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_palette() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(utils::find("fun_gg_empty_graph", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_empty_graph() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(utils::find("fun_gg_scatter", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_gg_scatter() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(utils::find("fun_close", mode = "function")) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_close() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end other required function checking
-    # package checking
-    if(plot == TRUE){
-        fun_pack(req.package = c("ggplot2"), lib.path = lib.path)
-    }
-    # end package checking
-    # main code
-    # na and Inf detection and removal (done now to be sure of the correct length of categ)
-    data1.removed.row.nb <- NULL
-    data1.removed.rows <- NULL
-    data2.removed.row.nb <- NULL
-    data2.removed.rows <- NULL
-    if(any(is.na(data1[, c(x1, y1)])) | any(is.infinite(data1[, x1])) | any(is.infinite(data1[, y1]))){
-        tempo.na <- unlist(lapply(lapply(c(data1[c(x1, y1)]), FUN = is.na), FUN = which))
-        tempo.inf <- unlist(lapply(lapply(c(data1[c(x1, y1)]), FUN = is.infinite), FUN = which))
-        data1.removed.row.nb <- sort(unique(c(tempo.na, tempo.inf)))
-        if(length(data1.removed.row.nb) > 0){
-            data1.removed.rows <- data1[data1.removed.row.nb, ]
-        }
-        if(length(data1.removed.row.nb) == nrow(data1)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE NA, NaN, -Inf OR Inf DETECTED IN EACH ROW OF data1. FUNCTION CANNOT BE USED ON EMPTY DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(length(data1.removed.row.nb) > 0){
-            data1 <- data1[-data1.removed.row.nb, ]
-        }
-        if(nrow(data1) == 0L){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 1")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x1, y1), collapse = " "), " OF data1 AND CORRESPONDING ROWS REMOVED (SEE $data1.removed.row.nb AND $data1.removed.rows)")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }else{
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NO NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x1, y1), collapse = " "), " OF data1. NO ROW REMOVED")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    if( ! is.null(data2)){
-        if(any(is.na(data2[, c(x2, y2)])) | any(is.infinite(data2[, x2])) | any(is.infinite(data2[, y2]))){
-            tempo.na <- unlist(lapply(lapply(c(data2[c(x2, y2)]), FUN = is.na), FUN = which))
-            tempo.inf <- unlist(lapply(lapply(c(data2[c(x2, y2)]), FUN = is.infinite), FUN = which))
-            data2.removed.row.nb <- sort(unique(c(tempo.na, tempo.inf)))
-            if(length(data2.removed.row.nb) > 0){
-                data2.removed.rows <- data2[data2.removed.row.nb, ]
-            }
-            if(length(data2.removed.row.nb) == nrow(data2)){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": AT LEAST ONE NA, NaN, -Inf OR Inf DETECTED IN EACH ROW OF data2. FUNCTION CANNOT BE USED ON EMPTY DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            if(length(data2.removed.row.nb) > 0){
-                data2 <- data2[-data2.removed.row.nb, ]
-            }
-            if(nrow(data2) == 0L){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x2, y2), collapse = " "), " OF data2 AND CORRESPONDING ROWS REMOVED (SEE $data2.removed.row.nb AND $data2.removed.rows)")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }else{
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NO NA, NaN, -Inf OR Inf DETECTED IN COLUMN ", paste(c(x2, y2), collapse = " "), " OF data2. NO ROW REMOVED")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end na and Inf detection and removal (done now to be sure of the correct length of categ)
-    # row annotation (dot number)
-    # data1 <- data1[ ! duplicated(data1[, c(x1, y1)]), ] # do not remove the dots that have same x and y values, because they will have different dot number -> not the same position on the matrices (so true for symmetric matrices)
-    data1 <- cbind(data1, DOT_NB = 1:nrow(data1), stringsAsFactors = TRUE)
-    if( ! is.null(data2)){
-        # data2 <- data2[ ! duplicated(data2[, c(x2, y2)]), ] # do not remove the dots that have same x and y values, because they will have different dot number -> not the same position on the matrices (so true for symmetric matrices)
-        data2 <- cbind(data2, DOT_NB = 1:nrow(data2), stringsAsFactors = TRUE)
-    }
-    # end row annotation (dot number)
-    
-    
-    
-    
-    # Method using x unit interval 
-    # may be create vector of each column to increase speed
-    x.data1.l <- NULL # x coord of the y upper and lower limits defined on the data1 cloud for left step line
-    x.data1.r <- NULL # x coord of the y upper and lower limits defined on the data1 cloud for right step line
-    y.data1.down.limit.l <- NULL # lower limit of the data1 cloud for left step line
-    y.data1.top.limit.l <- NULL # upper limit of the data1 cloud for left step line
-    y.data1.down.limit.r <- NULL # lower limit of the data1 cloud for right step line
-    y.data1.top.limit.r <- NULL # upper limit of the data1 cloud for left step line
-    if(any(data1[, x1] %in% c(Inf, -Inf))){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE x1 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    x.range <- range(data1[, x1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    if(suppressWarnings(any(x.range %in% c(Inf, -Inf)))){
-        tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED x.range CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1[, y1] %in% c(Inf, -Inf))){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE data1 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE y1 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    y.range <- range(data1[, y1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    if(suppressWarnings(any(x.range %in% c(Inf, -Inf)))){
-        tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED y.range CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    x.range.plot <- range(data1[, x1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    y.range.plot <- range(data1[, y1], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    if( ! is.null(data2)){
-        if(any(data2[, x2] %in% c(Inf, -Inf))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE data2 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE x2 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        x.range.plot <- range(data1[, x1], data2[, x2], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-        if(any(data2[, y2] %in% c(Inf, -Inf))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE data2 ARGUMENT CONTAINS -Inf OR Inf VALUES IN THE y2 COLUMN, THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        y.range.plot <- range(data1[, y1], data2[, y2], na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    }
-    if(suppressWarnings(any(x.range.plot %in% c(Inf, -Inf)))){
-        tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED x.range.plot CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 (AND data2?) ARGUMENTS ARE NA OR Inf ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(suppressWarnings(any(y.range.plot %in% c(Inf, -Inf)))){
-        tempo.cat <- paste0("ERROR IN ", function.name, " COMPUTED y.range.plot CONTAINS Inf VALUES, BECAUSE VALUES FROM data1 (AND data2?) ARGUMENTS ARE NA OR Inf ONLY")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(x.range.split)){
-        # data.frame ordering to slide the window from small to big values + sliding window definition
-        data1 <- data1[order(data1[, x1], na.last = TRUE), ]
-        if( ! is.null(data2)){
-            data2 <- data2[order(data2[, x2], na.last = TRUE), ]
-        }
-        x.win.size <- abs(diff(x.range) / x.range.split) # in unit of x-axis
-        step <- x.win.size / x.step.factor
-        # end data.frame ordering to slide the window from small to big values + sliding window definition
-        # x-axis sliding and y-axis limits of the data1 cloud -> y significant data2
-        loop.nb <- ceiling((diff(x.range) - x.win.size) / step) # x.win.size + n * step covers the x range if x.win.size + n * step >= diff(x.range), thus if n >= (diff(x.range) - x.win.size) / step 
-        y.outside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are upper or lower than the frame
-        y.inside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are not upper or lower than the frame
-        y.data1.median <- median(data1[, y1], na.rm = TRUE) # will be used for sliding windows without data1 in it
-        if( ! is.null(data2)){
-            y.outside.data2.dot.nb <- integer() # vector that will contain the selected 1D coordinates (i.e., dots) of data2 that are upper or lower than the data1 frame
-            y.inside.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are not upper or lower than the data1 frame
-            y.unknown.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are problematic: data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots
-            # recover data2 dots outside the range of data1
-            if(any(data2[, x2] < x.range[1])){
-                y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[data2[, x2] < x.range[1]])
-                #tempo.warn & indicate the interval
-            }
-            if(any(data2[, x2] > x.range[2])){
-                y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[data2[, x2] > x.range[2]])
-                #tempo.warn & indicate the interval
-            }
-            # end recover data2 dots outside the range of data1
-        }
-        # loop.ini.time <- as.numeric(Sys.time())
-        for(i1 in 0:(loop.nb + 1)){
-            min.pos <- x.range[1] + step * i1 # lower position of the sliding window in data1
-            max.pos <- min.pos + x.win.size # upper position of the sliding window in data1
-            x.data1.l <- c(x.data1.l, min.pos, min.pos + step) # min.pos + step to make the steps
-            x.data1.r <- c(x.data1.r, max.pos, max.pos + step) # max.pos + step to make the steps
-            x.data1.dot.here <- data1[, x1] >= min.pos & data1[, x1] < max.pos # is there data1 dot present in the sliding window, considering the x axis?
-            if( ! is.null(data2)){
-                x.data2.dot.here <- data2[, x2] >= min.pos & data2[, x2] < max.pos # is there data2 dot present in the sliding window, considering the x axis?
-            }
-            # recover the data1 dots outside the frame
-            if(any(x.data1.dot.here == TRUE)){
-                tempo.y.data1.top.limit <- quantile(data1[x.data1.dot.here, y1], probs = 1 - error, na.rm = TRUE)
-                tempo.y.data1.down.limit <- quantile(data1[x.data1.dot.here, y1], probs = 0 + error, na.rm = TRUE)
-                y.data1.top.limit.l <- c(y.data1.top.limit.l, tempo.y.data1.top.limit, tempo.y.data1.top.limit)
-                y.data1.down.limit.l <- c(y.data1.down.limit.l, tempo.y.data1.down.limit, tempo.y.data1.down.limit)
-                y.data1.top.limit.r <- c(y.data1.top.limit.r, tempo.y.data1.top.limit, tempo.y.data1.top.limit)
-                y.data1.down.limit.r <- c(y.data1.down.limit.r, tempo.y.data1.down.limit, tempo.y.data1.down.limit)
-                y.data1.dot.signif <- ( ! ((data1[, y1] <= tempo.y.data1.top.limit) & (data1[, y1] >= tempo.y.data1.down.limit))) & x.data1.dot.here # is there data1 dot present in the sliding window, above or below the data1 limits, considering the y axis?
-                y.data1.dot.not.signif <- x.data1.dot.here & ! y.data1.dot.signif
-                y.outside.data1.dot.nb <- c(y.outside.data1.dot.nb, data1$DOT_NB[y.data1.dot.signif]) # recover the row number of data1
-                y.outside.data1.dot.nb <- unique(y.outside.data1.dot.nb)
-                y.inside.data1.dot.nb <- c(y.inside.data1.dot.nb, data1$DOT_NB[y.data1.dot.not.signif])
-                y.inside.data1.dot.nb <- unique(y.inside.data1.dot.nb)
-            }else{
-                y.data1.top.limit.l <- c(y.data1.top.limit.l, y.data1.median, y.data1.median)
-                y.data1.down.limit.l <- c(y.data1.down.limit.l, y.data1.median, y.data1.median)
-                y.data1.top.limit.r <- c(y.data1.top.limit.r, y.data1.median, y.data1.median)
-                y.data1.down.limit.r <- c(y.data1.down.limit.r, y.data1.median, y.data1.median)
-            }
-            # end recover the data1 dots outside the frame
-            # recover the data2 dots outside the frame
-            if( ! is.null(data2)){
-                if(any(x.data1.dot.here == TRUE) & any(x.data2.dot.here == TRUE)){ 
-                    y.data2.dot.signif <- ( ! ((data2[, y2] <= tempo.y.data1.top.limit) & (data2[, y2] >= tempo.y.data1.down.limit))) & x.data2.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the y axis?
-                    y.data2.dot.not.signif <- x.data2.dot.here & ! y.data2.dot.signif
-                    y.outside.data2.dot.nb <- c(y.outside.data2.dot.nb, data2$DOT_NB[y.data2.dot.signif])
-                    y.outside.data2.dot.nb <- unique(y.outside.data2.dot.nb)
-                    y.inside.data2.dot.nb <- c(y.inside.data2.dot.nb, data2$DOT_NB[y.data2.dot.not.signif])
-                    y.inside.data2.dot.nb <- unique(y.inside.data2.dot.nb)
-                }else if(any(x.data1.dot.here == FALSE) & any(x.data2.dot.here == TRUE)){ # problem: data2 dots in the the window but no data1 dots to generates the quantiles
-                    y.unknown.data2.dot.nb <- c(y.unknown.data2.dot.nb, data2$DOT_NB[x.data2.dot.here])
-                    y.unknown.data2.dot.nb <- unique(y.unknown.data2.dot.nb)
-                    #tempo.warn & indicate the interval
-                    
-                    
-                    
-                    
-                    # tempo.warn <- paste0("FROM FUNCTION ", function.name, ": THE [", round(min.pos, 3), " ; ", round(max.pos, 3), "] INTERVAL DOES NOT CONTAIN data1 X VALUES BUT CONTAINS data2 X VALUES WHICH CANNOT BE EVALUATED.\nTHE CONCERNED data2 ROW NUMBERS ARE:\n", paste(which(x.data1.dot.here == FALSE & x.data2.dot.here == TRUE), collapse = "\n"))
-                    # warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            # end recover the data2 dots outside the frame
-            # if(any(i1 == seq(1, loop.nb, 500))){
-            # loop.fin.time <- as.numeric(Sys.time()) # time of process end
-            # cat(paste0("COMPUTATION TIME OF LOOP ", i1, " / ", loop.nb, ": ", as.character(lubridate::seconds_to_period(round(loop.fin.time - loop.ini.time))), "\n"))
-            # }
-        }
-        if(max.pos < x.range[2]){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE SLIDING WINDOW HAS NOT REACHED THE MAX VALUE OF data1 ON THE X-AXIS: ", max.pos, " VERSUS ", x.range[2])
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        y.incon.data1.dot.nb.final <- unique(c(y.outside.data1.dot.nb[y.outside.data1.dot.nb %in% y.inside.data1.dot.nb], y.inside.data1.dot.nb[y.inside.data1.dot.nb %in% y.outside.data1.dot.nb])) # inconsistent dots: if a row number of y.inside.data1.dot.nb is present in y.outside.data1.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
-        y.outside.data1.dot.nb.final <- y.outside.data1.dot.nb[ ! (y.outside.data1.dot.nb %in% y.incon.data1.dot.nb.final)] # inconsistent dots removed from the outside list
-        y.inside.data1.dot.nb.final <- y.inside.data1.dot.nb[ ! (y.inside.data1.dot.nb %in% y.incon.data1.dot.nb.final)] # inconsistent dots removed from the inside list
-        if( ! is.null(data2)){
-            # if some unknown dots are also inside, and/or outside, they are put in the inside and/or outside. Ok, because then the intersection between inside and outside is treated -> inconsistent dots
-            tempo.unknown.out <- y.unknown.data2.dot.nb[y.unknown.data2.dot.nb %in% y.outside.data2.dot.nb]
-            y.outside.data2.dot.nb <- unique(c(y.outside.data2.dot.nb, tempo.unknown.out)) # if a row number of y.unknown.data2.dot.nb is present in y.outside.data2.dot.nb, it is put into outside
-            tempo.unknown.in <- y.unknown.data2.dot.nb[y.unknown.data2.dot.nb %in% y.inside.data2.dot.nb]
-            y.inside.data2.dot.nb <- unique(c(y.inside.data2.dot.nb, tempo.unknown.in)) # if a row number of y.unknown.data2.dot.nb is present in y.inside.data2.dot.nb, it is put into inside
-            y.unknown.data2.dot.nb.final <- y.unknown.data2.dot.nb[ ! (y.unknown.data2.dot.nb %in% c(y.outside.data2.dot.nb, y.inside.data2.dot.nb))] # then dots also in inside and outside are remove from unknown
-            y.incon.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb[y.outside.data2.dot.nb %in% y.inside.data2.dot.nb], y.inside.data2.dot.nb[y.inside.data2.dot.nb %in% y.outside.data2.dot.nb])) # inconsistent dots: if a row number of y.inside.data2.dot.nb is present in y.outside.data2.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
-            y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb[ ! (y.outside.data2.dot.nb %in% y.incon.data2.dot.nb.final)] # inconsistent dots removed from the outside list
-            y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb[ ! (y.inside.data2.dot.nb %in% y.incon.data2.dot.nb.final)] # inconsistent dots removed from the inside list
-        }
-        # end x-axis sliding and y-axis limits of the data1 cloud -> y significant data2
-    }
-    # end Method using x unit interval 
-    
-    
-    
-    
-    # Method using y unit interval 
-    y.data1.d <- NULL # y coord of the x upper and lower limits defined on the data1 cloud for down step line
-    y.data1.t <- NULL # y coord of the x upper and lower limits defined on the data1 cloud for top step line
-    x.data1.left.limit.d <- NULL # left limit of the data1 cloud for down step line
-    x.data1.right.limit.d <- NULL # right limit of the data1 cloud for down step line
-    x.data1.left.limit.t <- NULL # left limit of the data1 cloud for top step line
-    x.data1.right.limit.t <- NULL # right limit of the data1 cloud for top step line
-    if( ! is.null(y.range.split)){
-        # data.frame ordering to slide the window from small to big values + sliding window definition
-        data1 <- data1[order(data1[, y1], na.last = TRUE), ]
-        if( ! is.null(data2)){
-            data2 <- data2[order(data2[, y2], na.last = TRUE), ]
-        }
-        y.win.size <- abs(diff(y.range) / y.range.split) # in unit of y-axis
-        step <- y.win.size / y.step.factor
-        # end data.frame ordering to slide the window from small to big values + sliding window definition
-        # y-axis sliding and x-axis limits of the data1 cloud -> x significant data2
-        loop.nb <- ceiling((diff(y.range) - y.win.size) / step) # y.win.size + n * step covers the y range if y.win.size + n * step >= diff(y.range), thus if n >= (diff(y.range) - y.win.size) / step 
-        x.outside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are upper or lower than the frame
-        x.inside.data1.dot.nb <- integer() # vector that will contain the selected rows numbers of data1 that are not upper or lower than the frame
-        x.data1.median <- median(data1[, x1], na.rm = TRUE) # will be used for sliding window without data1 in it
-        if( ! is.null(data2)){
-            x.outside.data2.dot.nb <- integer() # vector that will contain the selected 1D coordinates (i.e., dots) of data2 that are upper or lower than the data1 frame
-            x.inside.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are not upper or lower than the data1 frame
-            x.unknown.data2.dot.nb <- integer() # vector that will contain the 1D coordinates (i.e., dots) of data2 that are problematic: data2 dots outside of the range of data1, or data2 dots in a sliding window without data1 dots
-            # recover data2 dots outside the range of data1
-            if(any(data2[, y2] < y.range[1])){
-                x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[data2[, y2] < y.range[1]])
-            }
-            if(any(data2[, y2] > y.range[2])){
-                x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[data2[, y2] > y.range[2]])
-            }
-            # end recover data2 dots outside the range of data1
-        }
-        # loop.ini.time <- as.numeric(Sys.time())
-        for(i1 in 0:(loop.nb + 1)){
-            min.pos <- y.range[1] + step * i1 # lower position of the sliding window in data1
-            max.pos <- min.pos + y.win.size # upper position of the sliding window in data1
-            y.data1.d <- c(y.data1.d, min.pos, min.pos + step) # min.pos + step to make the steps
-            y.data1.t <- c(y.data1.t, max.pos, max.pos + step) # max.pos + step to make the steps
-            y.data1.dot.here <- data1[, y1] >= min.pos & data1[, y1] < max.pos # is there data1 dot present in the sliding window, considering the y axis?
-            if( ! is.null(data2)){
-                y.data2.dot.here <- data2[, y2] >= min.pos & data2[, y2] < max.pos # is there data2 dot present in the sliding window, considering the y axis?
-            }
-            # recover the data1 dots outside the frame
-            if(any(y.data1.dot.here == TRUE)){
-                tempo.x.data1.right.limit <- quantile(data1[y.data1.dot.here, x1], probs = 1 - error, na.rm = TRUE)
-                tempo.x.data1.left.limit <- quantile(data1[y.data1.dot.here, x1], probs = 0 + error, na.rm = TRUE)
-                x.data1.right.limit.d <- c(x.data1.right.limit.d, tempo.x.data1.right.limit, tempo.x.data1.right.limit)
-                x.data1.left.limit.d <- c(x.data1.left.limit.d, tempo.x.data1.left.limit, tempo.x.data1.left.limit)
-                x.data1.right.limit.t <- c(x.data1.right.limit.t, tempo.x.data1.right.limit, tempo.x.data1.right.limit)
-                x.data1.left.limit.t <- c(x.data1.left.limit.t, tempo.x.data1.left.limit, tempo.x.data1.left.limit)
-                x.data1.dot.signif <- ( ! ((data1[, x1] <= tempo.x.data1.right.limit) & (data1[, x1] >= tempo.x.data1.left.limit))) & y.data1.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the x axis?
-                x.data1.dot.not.signif <- y.data1.dot.here & ! x.data1.dot.signif
-                x.outside.data1.dot.nb <- c(x.outside.data1.dot.nb, data1$DOT_NB[x.data1.dot.signif]) # recover the row number of data1
-                x.outside.data1.dot.nb <- unique(x.outside.data1.dot.nb)
-                x.inside.data1.dot.nb <- c(x.inside.data1.dot.nb, data1$DOT_NB[x.data1.dot.not.signif])
-                x.inside.data1.dot.nb <- unique(x.inside.data1.dot.nb)
-            }else{
-                x.data1.right.limit.d <- c(x.data1.right.limit.d, x.data1.median, x.data1.median)
-                x.data1.left.limit.d <- c(x.data1.left.limit.d, x.data1.median, x.data1.median)
-                x.data1.right.limit.t <- c(x.data1.right.limit.t, x.data1.median, x.data1.median)
-                x.data1.left.limit.t <- c(x.data1.left.limit.t, x.data1.median, x.data1.median)
-            }
-            # end recover the data1 dots outside the frame
-            # recover the data2 dots outside the frame
-            if( ! is.null(data2)){
-                if(any(y.data1.dot.here == TRUE) & any(y.data2.dot.here == TRUE)){ 
-                    x.data2.dot.signif <- ( ! ((data2[, x2] <= tempo.x.data1.right.limit) & (data2[, x2] >= tempo.x.data1.left.limit))) & y.data2.dot.here # is there data2 dot present in the sliding window, above or below the data1 limits, considering the x axis?
-                    x.data2.dot.not.signif <- y.data2.dot.here & ! x.data2.dot.signif
-                    x.outside.data2.dot.nb <- c(x.outside.data2.dot.nb, data2$DOT_NB[x.data2.dot.signif])
-                    x.outside.data2.dot.nb <- unique(x.outside.data2.dot.nb)
-                    x.inside.data2.dot.nb <- c(x.inside.data2.dot.nb, data2$DOT_NB[x.data2.dot.not.signif])
-                    x.inside.data2.dot.nb <- unique(x.inside.data2.dot.nb)
-                }else if(any(y.data1.dot.here == FALSE) & any(y.data2.dot.here == TRUE)){ # recover the data2 dots outside the range of the data1 cloud
-                    x.unknown.data2.dot.nb <- c(x.unknown.data2.dot.nb, data2$DOT_NB[y.data2.dot.here])
-                    x.unknown.data2.dot.nb <- unique(x.unknown.data2.dot.nb)
-                    
-                    
-                    
-                    # tempo.warn <- paste0("FROM FUNCTION ", function.name, ": THE [", round(min.pos, 3), " ; ", round(max.pos, 3), "] INTERVAL DOES NOT CONTAIN data1 Y VALUES BUT CONTAINS data2 Y VALUES WHICH CANNOT BE EVALUATED.\nTHE CONCERNED data2 ROW NUMBERS ARE:\n", paste(which(y.data1.dot.here == FALSE & y.data2.dot.here == TRUE), collapse = "\n"))
-                    # warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            # end recover the data2 dots outside the frame
-            # if(any(i1 == seq(1, loop.nb, 500))){
-            # loop.fin.time <- as.numeric(Sys.time()) # time of process end
-            # cat(paste0("COMPUTATION TIME OF LOOP ", i1, " / ", loop.nb, ": ", as.character(lubridate::seconds_to_period(round(loop.fin.time - loop.ini.time))), "\n"))
-            # }
-        }
-        if(max.pos < y.range[2]){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": THE SLIDING WINDOW HAS NOT REACHED THE MAX VALUE OF data1 ON THE Y-AXIS: ", max.pos, " VERSUS ", y.range[2])
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        x.incon.data1.dot.nb.final <- unique(c(x.outside.data1.dot.nb[x.outside.data1.dot.nb %in% x.inside.data1.dot.nb], x.inside.data1.dot.nb[x.inside.data1.dot.nb %in% x.outside.data1.dot.nb])) # inconsistent dots: if a row number of x.inside.data1.dot.nb is present in x.outside.data1.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
-        x.outside.data1.dot.nb.final <- x.outside.data1.dot.nb[ ! (x.outside.data1.dot.nb %in% x.incon.data1.dot.nb.final)] # inconsistent dots removed from the outside list
-        x.inside.data1.dot.nb.final <- x.inside.data1.dot.nb[ ! (x.inside.data1.dot.nb %in% x.incon.data1.dot.nb.final)] # inconsistent dots removed from the inside list
-        if( ! is.null(data2)){
-            # if some unknown dots are also inside, and/or outside, they are put in the inside and/or outside. Ok, because then the intersection between inside and outside is treated -> inconsistent dots
-            tempo.unknown.out <- x.unknown.data2.dot.nb[x.unknown.data2.dot.nb %in% x.outside.data2.dot.nb]
-            x.outside.data2.dot.nb <- unique(c(x.outside.data2.dot.nb, tempo.unknown.out)) # if a row number of x.unknown.data2.dot.nb is present in x.outside.data2.dot.nb, it is put into outside
-            tempo.unknown.in <- x.unknown.data2.dot.nb[x.unknown.data2.dot.nb %in% x.inside.data2.dot.nb]
-            x.inside.data2.dot.nb <- unique(c(x.inside.data2.dot.nb, tempo.unknown.in)) # if a row number of x.unknown.data2.dot.nb is present in x.inside.data2.dot.nb, it is put into inside
-            x.unknown.data2.dot.nb.final <- x.unknown.data2.dot.nb[ ! (x.unknown.data2.dot.nb %in% c(x.outside.data2.dot.nb, x.inside.data2.dot.nb))] # then dots also in inside and outside are remove from unknown
-            x.incon.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb[x.outside.data2.dot.nb %in% x.inside.data2.dot.nb], x.inside.data2.dot.nb[x.inside.data2.dot.nb %in% x.outside.data2.dot.nb])) # inconsistent dots: if a row number of x.inside.data2.dot.nb is present in x.outside.data2.dot.nb (and vice versa), it means that during the sliding, a dot has been sometime inside, sometime outside -> removed from the outside list
-            x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb[ ! (x.outside.data2.dot.nb %in% x.incon.data2.dot.nb.final)] # inconsistent dots removed from the outside list
-            x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb[ ! (x.inside.data2.dot.nb %in% x.incon.data2.dot.nb.final)] # inconsistent dots removed from the inside list
-        }
-        # end y-axis sliding and x-axis limits of the data1 cloud -> x significant data2
-    }
-    # end Method using y unit interval 
-    
-    
-    
-    # recovering the frame coordinates
-    hframe = rbind(
-        data.frame(
-            x = if(is.null(x.data1.l)){NULL}else{x.data1.l}, 
-            y = if(is.null(x.data1.l)){NULL}else{y.data1.down.limit.l}, 
-            kind = if(is.null(x.data1.l)){NULL}else{"down.frame1"},
-            stringsAsFactors = TRUE
-        ), 
-        data.frame(
-            x = if(is.null(x.data1.r)){NULL}else{x.data1.r}, 
-            y = if(is.null(x.data1.r)){NULL}else{y.data1.down.limit.r}, 
-            kind = if(is.null(x.data1.r)){NULL}else{"down.frame2"},
-            stringsAsFactors = TRUE
-        ), 
-        data.frame(
-            x = if(is.null(x.data1.l)){NULL}else{x.data1.l}, 
-            y = if(is.null(x.data1.l)){NULL}else{y.data1.top.limit.l}, 
-            kind = if(is.null(x.data1.l)){NULL}else{"top.frame1"},
-            stringsAsFactors = TRUE
-        ), 
-        data.frame(
-            x = if(is.null(x.data1.r)){NULL}else{x.data1.r}, 
-            y = if(is.null(x.data1.r)){NULL}else{y.data1.top.limit.r}, 
-            kind = if(is.null(x.data1.r)){NULL}else{"top.frame2"},
-            stringsAsFactors = TRUE
-        ), 
-        stringsAsFactors = TRUE
-    )
-    vframe = rbind(
-        data.frame(
-            x = if(is.null(y.data1.d)){NULL}else{x.data1.left.limit.d}, 
-            y = if(is.null(y.data1.d)){NULL}else{y.data1.d}, 
-            kind = if(is.null(y.data1.d)){NULL}else{"left.frame1"},
-            stringsAsFactors = TRUE
-        ), 
-        data.frame(
-            x = if(is.null(y.data1.t)){NULL}else{x.data1.left.limit.t}, 
-            y = if(is.null(y.data1.t)){NULL}else{y.data1.t}, 
-            kind = if(is.null(y.data1.t)){NULL}else{"left.frame2"},
-            stringsAsFactors = TRUE
-        ), 
-        data.frame(
-            x = if(is.null(y.data1.d)){NULL}else{x.data1.right.limit.d}, 
-            y = if(is.null(y.data1.d)){NULL}else{y.data1.d}, 
-            kind = if(is.null(y.data1.d)){NULL}else{"right.frame1"},
-            stringsAsFactors = TRUE
-        ),
-        data.frame(
-            x = if(is.null(y.data1.t)){NULL}else{x.data1.right.limit.t}, 
-            y = if(is.null(y.data1.t)){NULL}else{y.data1.t}, 
-            kind = if(is.null(y.data1.t)){NULL}else{"right.frame2"},
-            stringsAsFactors = TRUE
-        ), 
-        stringsAsFactors = TRUE
-    )
-    # end recovering the frame coordinates
-    # recovering the dot coordinates
-    data1.signif.dot <- NULL
-    data1.non.signif.dot <- NULL
-    data1.incon.dot <- NULL
-    data2.signif.dot <- NULL
-    data2.non.signif.dot <- NULL
-    data2.unknown.dot <- NULL
-    data2.incon.dot <- NULL
-    if(( ! is.null(x.range.split)) & ( ! is.null(y.range.split))){
-        # inconsistent dots recovery 
-        if(length(unique(c(x.incon.data1.dot.nb.final, y.incon.data1.dot.nb.final))) > 0){
-            data1.incon.dot <- data1[data1$DOT_NB %in% unique(c(x.incon.data1.dot.nb.final, y.incon.data1.dot.nb.final)), ] # if a dot in inconsistent in x or y -> classified as inconsistent (so unique() used)
-            # removal of the inconsistent dot in the other classifications
-            x.inside.data1.dot.nb.final <- x.inside.data1.dot.nb.final[ ! x.inside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            y.inside.data1.dot.nb.final <- y.inside.data1.dot.nb.final[ ! y.inside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            x.outside.data1.dot.nb.final <- x.outside.data1.dot.nb.final[ ! x.outside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            y.outside.data1.dot.nb.final <- y.outside.data1.dot.nb.final[ ! y.outside.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            x.unknown.data1.dot.nb.final <- x.unknown.data1.dot.nb.final[ ! x.unknown.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            y.unknown.data1.dot.nb.final <- y.unknown.data1.dot.nb.final[ ! y.unknown.data1.dot.nb.final %in% data1.incon.dot$DOT_NB]
-            # end removal of the inconsistent dot in the other classifications
-        }
-        if( ! is.null(data2)){
-            if(length(unique(c(x.incon.data2.dot.nb.final, y.incon.data2.dot.nb.final))) > 0){
-                data2.incon.dot <- data2[data2$DOT_NB %in% unique(c(x.incon.data2.dot.nb.final, y.incon.data2.dot.nb.final)), ]
-                # removal of the inconsistent dot in the other classifications
-                x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                x.unknown.data2.dot.nb.final <- x.unknown.data2.dot.nb.final[ ! x.unknown.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                y.unknown.data2.dot.nb.final <- y.unknown.data2.dot.nb.final[ ! y.unknown.data2.dot.nb.final %in% data2.incon.dot$DOT_NB]
-                # end removal of the inconsistent dot in the other classifications
-            }
-        }
-        # end inconsistent dots recovery 
-        # unknown dots recovery 
-        if( ! is.null(data2)){
-            if(data2.pb.dot == "signif"){
-                x.outside.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
-                x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% x.unknown.data2.dot.nb.final] # remove x.unknown.data2.dot.nb.final from x.inside.data2.dot.nb.final
-                y.outside.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
-                y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% y.unknown.data2.dot.nb.final] # remove y.unknown.data2.dot.nb.final from y.inside.data2.dot.nb.final
-                x.unknown.data2.dot.nb.final <- NULL
-                y.unknown.data2.dot.nb.final <- NULL
-                data2.unknown.dot <- NULL
-            }else if(data2.pb.dot == "not.signif"){
-                x.inside.data2.dot.nb.final <- unique(c(x.inside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
-                x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% x.unknown.data2.dot.nb.final] # remove x.unknown.data2.dot.nb.final from x.outside.data2.dot.nb.final
-                y.inside.data2.dot.nb.final <- unique(c(y.inside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
-                y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% y.unknown.data2.dot.nb.final] # remove y.unknown.data2.dot.nb.final from y.outside.data2.dot.nb.final
-                x.unknown.data2.dot.nb.final <- NULL
-                y.unknown.data2.dot.nb.final <- NULL
-                data2.unknown.dot <- NULL
-            }else if(data2.pb.dot == "unknown"){
-                if(length(unique(c(x.unknown.data2.dot.nb.final, y.unknown.data2.dot.nb.final))) > 0){
-                    data2.unknown.dot <- data2[data2$DOT_NB %in% unique(c(x.unknown.data2.dot.nb.final, y.unknown.data2.dot.nb.final)), ] # if a dot in unknown in x or y -> classified as unknown (so unique() used)
-                    x.outside.data2.dot.nb.final <- x.outside.data2.dot.nb.final[ ! x.outside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove x.unknown.data2.dot.nb.final from x.outside.data2.dot.nb.final
-                    x.inside.data2.dot.nb.final <- x.inside.data2.dot.nb.final[ ! x.inside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove x.unknown.data2.dot.nb.final from x.inside.data2.dot.nb.final
-                    y.outside.data2.dot.nb.final <- y.outside.data2.dot.nb.final[ ! y.outside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove y.unknown.data2.dot.nb.final from y.outside.data2.dot.nb.final
-                    y.inside.data2.dot.nb.final <- y.inside.data2.dot.nb.final[ ! y.inside.data2.dot.nb.final %in% data2.unknown.dot$DOT_NB] # remove y.unknown.data2.dot.nb.final from y.inside.data2.dot.nb.final
-                }
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        # end unknown dots recovery 
-        # sign and non sign dot recovery
-        if(xy.cross.kind == "|"){ # here the problem is to deal with significant dots depending on x and y. Thus I start with that, recover dots finally non significant in outside and put them in inside (when &), and remove from inside the dots in outside
-            if(length(unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final))) > 0){
-                tempo.outside <- unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final)) # union so unique() used
-                tempo.inside <- unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final))
-                tempo.inside <- tempo.inside[ ! tempo.inside %in% tempo.outside]
-                data1.signif.dot <- data1[data1$DOT_NB %in% tempo.outside, ]
-                data1.non.signif.dot <- data1[data1$DOT_NB %in% tempo.inside, ]
-            }else{
-                data1.non.signif.dot <- data1[unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
-            }
-        }else if(xy.cross.kind == "&"){
-            if(sum(x.outside.data1.dot.nb.final %in% y.outside.data1.dot.nb.final) > 0){ # that is intersection
-                tempo.outside <- unique(x.outside.data1.dot.nb.final[x.outside.data1.dot.nb.final %in% y.outside.data1.dot.nb.final]) # intersection
-                tempo.outside.removed <- unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final))[ ! unique(c(x.outside.data1.dot.nb.final, y.outside.data1.dot.nb.final)) %in% tempo.outside]
-                tempo.inside <- unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final))
-                data1.signif.dot <- data1[data1$DOT_NB %in% tempo.outside, ]
-                data1.non.signif.dot <- data1[data1$DOT_NB %in% tempo.inside, ]
-            }else{
-                data1.non.signif.dot <- data1[unique(c(x.inside.data1.dot.nb.final, y.inside.data1.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
-            }
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! is.null(data2)){
-            if(xy.cross.kind == "|"){ # here the problem is to deal with significant dots depending on x and y. Thus I start with that, recover dots finally non significant in outside and put them in inside (when &), and remove from inside the dots in outside
-                if(length(unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final))) > 0){
-                    tempo.outside <- unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final)) # union so unique() used
-                    tempo.inside <- unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final))
-                    tempo.inside <- tempo.inside[ ! tempo.inside %in% tempo.outside]
-                    data2.signif.dot <- data2[data2$DOT_NB %in% tempo.outside, ]
-                    data2.non.signif.dot <- data2[data2$DOT_NB %in% tempo.inside, ]
-                }else{
-                    data2.non.signif.dot <- data2[unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
-                }
-            }else if(xy.cross.kind == "&"){
-                if(sum(x.outside.data2.dot.nb.final %in% y.outside.data2.dot.nb.final) > 0){ # that is intersection
-                    tempo.outside <- unique(x.outside.data2.dot.nb.final[x.outside.data2.dot.nb.final %in% y.outside.data2.dot.nb.final]) # intersection
-                    tempo.outside.removed <- unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final))[ ! unique(c(x.outside.data2.dot.nb.final, y.outside.data2.dot.nb.final)) %in% tempo.outside]
-                    tempo.inside <- unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final))
-                    data2.signif.dot <- data2[data2$DOT_NB %in% tempo.outside, ]
-                    data2.non.signif.dot <- data2[data2$DOT_NB %in% tempo.inside, ]
-                }else{
-                    data2.non.signif.dot <- data2[unique(c(x.inside.data2.dot.nb.final, y.inside.data2.dot.nb.final)), ] # if no outside dots, I recover all the inside dots and that's it
-                }
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        # end sign and non sign dot recovery
-    }else if(( ! is.null(x.range.split)) & is.null(y.range.split)){
-        # inconsistent dots recovery 
-        if(length(y.incon.data1.dot.nb.final) > 0){
-            data1.incon.dot <- data1[data1$DOT_NB %in% y.incon.data1.dot.nb.final, ]
-        }
-        if( ! is.null(data2)){
-            if(length(y.incon.data2.dot.nb.final) > 0){
-                data2.incon.dot <- data2[data2$DOT_NB %in% y.incon.data2.dot.nb.final, ]
-            }
-        }# end inconsistent dots recovery 
-        # unknown dots recovery 
-        if( ! is.null(data2)){
-            if(data2.pb.dot == "signif"){
-                y.outside.data2.dot.nb.final <- unique(c(y.outside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
-            }else if(data2.pb.dot == "not.signif"){
-                y.inside.data2.dot.nb.final <- unique(c(y.inside.data2.dot.nb.final, y.unknown.data2.dot.nb.final))
-            }else if(data2.pb.dot == "unknown"){
-                if(length(y.unknown.data2.dot.nb.final) > 0){
-                    data2.unknown.dot <- data2[data2$DOT_NB %in% y.unknown.data2.dot.nb.final, ]
-                }
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 6")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        # end unknown dots recovery 
-        # sign and non sign dot recovery
-        if(length(y.outside.data1.dot.nb.final) > 0){
-            data1.signif.dot <- data1[data1$DOT_NB %in% y.outside.data1.dot.nb.final, ]
-        }
-        if(length(y.inside.data1.dot.nb.final) > 0){
-            data1.non.signif.dot <- data1[data1$DOT_NB %in% y.inside.data1.dot.nb.final, ]
-        }
-        if( ! is.null(data2)){
-            if(length(y.outside.data2.dot.nb.final) > 0){
-                data2.signif.dot <- data2[data2$DOT_NB %in% y.outside.data2.dot.nb.final, ]
-            }
-            if(length(y.inside.data2.dot.nb.final) > 0){
-                data2.non.signif.dot <- data2[data2$DOT_NB %in% y.inside.data2.dot.nb.final, ]
-            }
-        }
-        # end sign and non sign dot recovery
-    }else if(is.null(x.range.split) & ( ! is.null(y.range.split))){
-        # inconsistent dots recovery 
-        if(length(x.incon.data1.dot.nb.final) > 0){
-            data1.incon.dot <- data1[data1$DOT_NB %in% x.incon.data1.dot.nb.final, ]
-        }
-        if( ! is.null(data2)){
-            if(length(x.incon.data2.dot.nb.final) > 0){
-                data2.incon.dot <- data2[data2$DOT_NB %in% x.incon.data2.dot.nb.final, ]
-            }
-        }# end inconsistent dots recovery 
-        # unknown dots recovery 
-        if( ! is.null(data2)){
-            if(data2.pb.dot == "signif"){
-                x.outside.data2.dot.nb.final <- unique(c(x.outside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
-            }else if(data2.pb.dot == "not.signif"){
-                x.inside.data2.dot.nb.final <- unique(c(x.inside.data2.dot.nb.final, x.unknown.data2.dot.nb.final))
-            }else if(data2.pb.dot == "unknown"){
-                if(length(x.unknown.data2.dot.nb.final) > 0){
-                    data2.unknown.dot <- data2[data2$DOT_NB %in% x.unknown.data2.dot.nb.final, ]
-                }
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 7")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-        # end unknown dots recovery 
-        # sign and non sign dot recovery
-        if(length(x.outside.data1.dot.nb.final) > 0){
-            data1.signif.dot <- data1[data1$DOT_NB %in% x.outside.data1.dot.nb.final, ]
-        }
-        if(length(x.inside.data1.dot.nb.final) > 0){
-            data1.non.signif.dot <- data1[data1$DOT_NB %in% x.inside.data1.dot.nb.final, ]
-        }
-        if( ! is.null(data2)){
-            if(length(x.outside.data2.dot.nb.final) > 0){
-                data2.signif.dot <- data2[data2$DOT_NB %in% x.outside.data2.dot.nb.final, ]
-            }
-            if(length(x.inside.data2.dot.nb.final) > 0){
-                data2.non.signif.dot <- data2[data2$DOT_NB %in% x.inside.data2.dot.nb.final, ]
-            }
-        }
-        # end sign and non sign dot recovery
-    }
-    # end recovering the dot coordinates
-    # verif
-    if(any(data1.signif.dot$DOT_NB %in% data1.non.signif.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", FUNCTION.NAME, ": CODE INCONSISTENCY 8")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1.non.signif.dot$DOT_NB %in% data1.signif.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", FUNCTION.NAME, ": CODE INCONSISTENCY 9")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1.signif.dot$DOT_NB %in% data1.incon.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 10")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1.incon.dot$DOT_NB %in% data1.signif.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 11")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1.non.signif.dot$DOT_NB %in% data1.incon.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 12")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(any(data1.incon.dot$DOT_NB %in% data1.non.signif.dot$DOT_NB)){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 13")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(data2)){
-        if(any(data2.signif.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 14")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.non.signif.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 15")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.signif.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 16")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.unknown.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 17")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.signif.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 18")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.incon.dot$DOT_NB %in% data2.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 19")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.non.signif.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 20")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.unknown.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 21")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.non.signif.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 22")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.incon.dot$DOT_NB %in% data2.non.signif.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 23")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.unknown.dot$DOT_NB %in% data2.incon.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 24")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(data2.incon.dot$DOT_NB %in% data2.unknown.dot$DOT_NB)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 25")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end verif
-    # plot
-    # recovering the axes data whatever plot or not
-    if(is.null(data2)){
-        axes <- fun_gg_scatter(data1 = list(data1), x = list(x1), y = list(y1), categ = list(NULL), color = list(fun_gg_palette(2)[2]), geom = list("geom_point"), alpha = list(0.5), x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, plot = FALSE, return = TRUE)$axes
-    }else{
-        axes <- fun_gg_scatter(data1 = list(data1, data2), x = list(x1, x2), y = list(y1, y2), categ = list(NULL, NULL), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1]), geom = list("geom_point", "geom_point"), alpha = list(0.5, 0.5), x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, plot = FALSE, return = TRUE)$axes
-    }
-    # end recovering the axes data whatever plot or not
-    if(plot == TRUE){
-        # add a categ for plot legend
-        tempo.df.name <- c("data1", "data1.signif.dot", "data1.incon.dot", "data2", "data2.signif.dot", "data2.unknown.dot", "data2.incon.dot")
-        tempo.class.name <- c("data1", "data1", "data1", "data2", "data2", "data2", "data2")
-        for(i2 in 1:length(tempo.df.name)){
-            if( ! is.null(get(tempo.df.name[i2], env = sys.nframe(), inherit = FALSE))){
-                assign(tempo.df.name[i2], data.frame(get(tempo.df.name[i2], env = sys.nframe(), inherit = FALSE), kind = tempo.class.name[i2]),
-                       stringsAsFactors = TRUE)
-            }
-        }
-        # end add a categ for plot legend
-        if(( ! is.null(x.range.split)) & ( ! is.null(y.range.split))){
-            if(graph.in.file == FALSE){
-                fun_open(pdf = FALSE)
-            }
-            tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe), x = list(x1, "x", "x"), y = list(y1, "y", "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-            if( ! is.null(tempo.graph$warn)){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            if( ! is.null(data1.signif.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe, data1.signif.dot), x = list(x1, "x", "x", x1), y = list(y1, "y", "y", y1), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
-            }
-            if( ! is.null(data1.incon.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, vframe, data1.incon.dot), x = list(x1, "x", "x", x1), y = list(y1, "y", "y", y1), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME" , "VERT FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
-            }
-            if( ! is.null(data2)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, hframe , vframe), x = list(x1, x2, "x", "x"), y = list(y1, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-                if( ! is.null(data2.signif.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
-                }
-                if( ! is.null(data2.incon.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
-                }
-                if( ! is.null(data2.unknown.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, hframe , vframe), x = list(x1, x2, x2, "x", "x"), y = list(y1, y2, y2, "y", "y"), categ = list("kind", "kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "HORIZ FRAME" , "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 12, title = "DATA2 + DATA2 UNKNOWN DOTS")
-                }
-            }
-        }else if(( ! is.null(x.range.split)) & is.null(y.range.split)){
-            if(graph.in.file == FALSE){
-                fun_open(pdf = FALSE)
-            }
-            tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe), x = list(x1, "x"), y = list(y1, "y"), categ = list("kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_path"), alpha = list(0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-            if( ! is.null(tempo.graph$warn)){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            if( ! is.null(data1.signif.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, data1.signif.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
-            }
-            if( ! is.null(data1.incon.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, hframe, data1.incon.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "HORIZ FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
-            }
-            if( ! is.null(data2)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, hframe), x = list(x1, x2, "x"), y = list(y1, y2, "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-                if( ! is.null(data2.signif.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
-                }
-                if( ! is.null(data2.incon.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
-                }
-                if( ! is.null(data2.unknown.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, hframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "HORIZ FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.1, 0.15), v = c(0.75, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 8, title = "DATA2 + DATA2 UNKNOWN DOTS")
-                }
-            }
-        }else if(is.null(x.range.split) & ( ! is.null(y.range.split))){
-            if(graph.in.file == FALSE){
-                fun_open(pdf = FALSE)
-            }
-            tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe), x = list(x1, "x"), y = list(y1, "y"), categ = list("kind", "kind"), legend.name = list("DATASET", "VERT FRAME"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_path"), alpha = list(0.5, 0.5), title = "DATA1", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-            if( ! is.null(tempo.graph$warn)){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            if( ! is.null(data1.signif.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe, data1.signif.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "VERT FRAME", "SIGNIF DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), "black"), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA1 SIGNIFICANT DOTS")
-            }
-            if( ! is.null(data1.incon.dot)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, vframe, data1.incon.dot), x = list(x1, "x", x1), y = list(y1, "y", y1), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "VERT FRAME", "INCONSISTENT DOTS"), color = list(fun_gg_palette(2)[2], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2), fun_gg_palette(7)[6]), geom = list("geom_point", "geom_path", "geom_point"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA1 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else{
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA1\nINCONSISTENT DOTS", text.size = 8, title = "DATA1 + DATA1 INCONSISTENT DOTS")
-            }
-            if( ! is.null(data2)){
-                if(graph.in.file == FALSE){
-                    fun_open(pdf = FALSE)
-                }
-                tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, vframe), x = list(x1, x2, "x"), y = list(y1, y2, "y"), categ = list("kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5), title = "DATA1 + DATA2", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                if( ! is.null(tempo.graph$warn)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-                if( ! is.null(data2.signif.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.signif.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "SIGNIF DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], "black", rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2 DOTS\nOUTSIDE THE FRAMES", text.size = 8, title = "DATA1 + DATA2 + DATA2 SIGNIFICANT DOTS")
-                }
-                if( ! is.null(data2.incon.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.incon.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "INCONSISTENT DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[6], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 INCONSISTENT DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nINCONSISTENT DOTS", text.size = 8, title = "DATA2 + DATA2 INCONSISTENT DOTS")
-                }
-                if( ! is.null(data2.unknown.dot)){
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    tempo.graph <- fun_gg_scatter(data1 = list(data1, data2, data2.unknown.dot, vframe), x = list(x1, x2, x2, "x"), y = list(y1, y2, y2, "y"), categ = list("kind", "kind", "kind", "kind"), legend.name = list("DATASET", "DATASET", "UNKNOWN DOTS", "VERT FRAME"), color = list(fun_gg_palette(2)[2], fun_gg_palette(2)[1], fun_gg_palette(7)[5], rep(hsv(h = c(0.5, 0.6), v = c(0.9, 1)), 2)), geom = list("geom_point", "geom_point", "geom_point", "geom_path"), alpha = list(0.5, 0.5, 0.5, 0.5), title = "DATA1 + DATA2 + DATA2 UNKNOWN DOTS", x.lim = x.range.plot, y.lim = y.range.plot, raster = raster, return = TRUE)
-                    if( ! is.null(tempo.graph$warn)){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") FROM fun_gg_scatter():\n", tempo.graph$warn)
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else{
-                    if(graph.in.file == FALSE){
-                        fun_open(pdf = FALSE)
-                    }
-                    fun_gg_empty_graph(text = "NO PLOT\nBECAUSE\nNO DATA2\nUNKNOWN DOTS", text.size = 8, title = "DATA2 + DATA2 UNKNOWN DOTS")
-                }
-            }
-        }
-    }
-    # end plot
-    if(warn.print == TRUE & ! is.null(warn)){
-        options(warning.length = 8170)
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    tempo.list <- list(data1.removed.row.nb = data1.removed.row.nb, data1.removed.rows = data1.removed.rows, data2.removed.row.nb = data2.removed.row.nb, data2.removed.rows = data2.removed.rows, hframe = hframe, vframe = vframe, data1.signif.dot = data1.signif.dot, data1.non.signif.dot = data1.non.signif.dot, data1.inconsistent.dot = data1.incon.dot, data2.signif.dot = data2.signif.dot, data2.non.signif.dot = data2.non.signif.dot, data2.unknown.dot = data2.unknown.dot, data2.inconsistent.dot = data2.incon.dot, axes = axes, warn = warn)
-    return(tempo.list)
+# 3 lines below inactivated because I put that above
+# if(is.null(categ[[i1]])){
+# data1[, "fake_categ"] <- paste0("Line_", i3)
+# }
+final.data.frame <- rbind(final.data.frame, tempo.data.frame, stringsAsFactors = TRUE)
 }
-
-
-################ Import
-
-
-######## fun_pack() #### check if R packages are present and import into the working environment
-
-
-fun_pack <- function(
-    req.package, 
-    load = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # check if the specified R packages are present in the computer and import them into the working environment
-    # ARGUMENTS
-    # req.package: character vector of package names to import
-    # load: logical. Load the package into the environement (using library())? Interesting if packages are not in default folders or for checking the functions names of packages using search()
-    # lib.path: optional character vector specifying the absolute pathways of the directories containing some of the listed packages in the req.package argument, if not in the default directories. Ignored if NULL
-    # RETURN
-    # nothing
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_pack(req.package = "nopackage")
-    # fun_pack(req.package = "ggplot2")
-    # fun_pack(req.package = "ggplot2", lib.path = "blablabla")
-    # DEBUGGING
-    # req.package = "ggplot2" ; lib.path = "C:/Program Files/R/R-3.5.1/library"
-    # req.package = "serpentine" ; lib.path = "C:/users/gael/appdata/roaming/python/python36/site-packages"
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = req.package, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = load, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    if(is.null(lib.path)){
-        lib.path <- .libPaths() # .libPaths(new = lib.path) # or .libPaths(new = c(.libPaths(), lib.path))
-    }else{
-        .libPaths(new = sub(x = lib.path, pattern = "/$|\\\\$", replacement = "")) # .libPaths(new = ) add path to default path. BEWARE: .libPaths() does not support / at the end of a submitted path. Thus check and replace last / or \\ in path
-        lib.path <- .libPaths()
-    }
-    tempo <- NULL
-    for(i1 in 1:length(req.package)){
-        if( ! req.package[i1] %in% rownames(utils::installed.packages(lib.loc = lib.path))){
-            tempo <- c(tempo, req.package[i1])
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0(
-            "ERROR IN ", 
-            function.name, 
-            ": PACKAGE", 
-            ifelse(length(tempo) == 1L, paste0("\n\n", tempo, "\n\n"), paste0("S\n", paste(tempo, collapse = "\n"), "\n")), 
-            "MUST BE INSTALLED IN", 
-            ifelse(length(lib.path) == 1L, "", " ONE OF THESE FOLDERS"), 
-            ":\n", 
-            paste(lib.path, collapse = "\n")
-        )
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if(load == TRUE){
-        for(i2 in 1:length(req.package)){
-            suppressMessages(suppressWarnings(suppressPackageStartupMessages(library(req.package[i2], lib.loc = lib.path, quietly = TRUE, character.only = TRUE))))
-        }
-    }
+data1[[i1]] <- final.data.frame
+geom[[i1]] <- "geom_line"
+if(length(color[[i1]])== 1L){
+color[[i1]] <- rep(color[[i1]], length(unique(data1[[i1]][ , categ[[i1]]])))
+}else if(length(color[[i1]]) != length(unique(data1[[i1]][ , categ[[i1]]]))){
+tempo.cat <- paste0("ERROR IN ", function.name, " geom_hline AND geom_vline CONVERSION TO FIT THE XLIM AND YLIM LIMITS OF THE DATA: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE THE LENGTH OF LEVELS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LEVELS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])))
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
 }
-
-
-######## fun_python_pack() #### check if python packages are present
-
-
-fun_python_pack <- function(
-    req.package, 
-    python.exec.path = NULL, 
-    lib.path = NULL, 
-    R.lib.path = NULL
-){
-    # AIM
-    # check if the specified python packages are present in the computer (no import)
-    # WARNINGS
-    # for python 3.7. Previous versions return an error "Error in sys$stdout$flush() : attempt to apply non-function"
-    # ARGUMENTS
-    # req.package: character vector of package names to import
-    # python.exec.path: optional character vector specifying the absolute pathways of the executable python file to use (associated to the packages to use). If NULL, the reticulate::import_from_path() function used in fun_python_pack() seeks for an available version of python.exe, and then uses python_config(python_version, required_module, python_versions). But might not be the correct one for the lib.path parameter specified. Thus, it is recommanded to do not leave NULL, notably when using computing clusters
-    # lib.path: optional character vector specifying the absolute pathways of the directories containing some of the listed packages in the req.package argument, if not in the default directories
-    # R.lib.path: absolute path of the reticulate packages, if not in the default folders
-    # RETURN
-    # nothing
-    # REQUIRED PACKAGES
-    # reticulate
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # fun_pack()
-    # EXAMPLES
-    # example of error message
-    # fun_python_pack(req.package = "nopackage")
-    # example without error message (require the installation of the python serpentine package from https://github.com/koszullab/serpentine
-    # fun_python_pack(req.package = "serpentine", python.exec.path = "C:/ProgramData/Anaconda3/python.exe", lib.path = "c:/programdata/anaconda3/lib/site-packages/")
-    # another example of error message
-    # fun_python_pack(req.package = "serpentine", lib.path = "blablabla")
-    # DEBUGGING
-    # req.package = "serpentine" ; python.exec.path = "C:/ProgramData/Anaconda3/python.exe" ; lib.path = "c:/programdata/anaconda3/lib/site-packages/" ; R.lib.path = NULL
-    # req.package = "bad" ; lib.path = NULL ; R.lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(utils::find("fun_pack", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_pack() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = req.package, class = "character", fun.name = function.name) ; eval(ee)
-    if( ! is.null(python.exec.path)){
-        tempo <- fun_check(data = python.exec.path, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(file.exists(python.exec.path))){ # separation to avoid the problem of tempo$problem == FALSE and python.exec.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": FILE PATH INDICATED IN THE python.exec.path ARGUMENT DOES NOT EXISTS:\n", paste(python.exec.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if( ! is.null(R.lib.path)){
-        tempo <- fun_check(data = R.lib.path, class = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(R.lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and R.lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE R.lib.path ARGUMENT DOES NOT EXISTS:\n", paste(R.lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # package checking
-    fun_pack(req.package = "reticulate", lib.path = R.lib.path)
-    # end package checking
-    # main code
-    if(is.null(python.exec.path)){
-        python.exec.path <- reticulate::py_run_string("
-import sys ;
-path_lib = sys.path
-") # python string
-        python.exec.path <- python.exec.path$path_lib
-    }
-    if(is.null(lib.path)){
-        lib.path <- reticulate::py_run_string("
-import sys ;
-path_lib = sys.path
-") # python string
-        lib.path <- lib.path$path_lib
-    }
-    reticulate::use_python(Sys.which(python.exec.path), required = TRUE) # required to avoid the use of erratic python exec by reticulate::import_from_path()
-    for(i1 in 1:length(req.package)){
-        tempo.try <- vector("list", length = length(lib.path))
-        for(i2 in 1:length(lib.path)){
-            tempo.try[[i2]] <- suppressWarnings(try(reticulate::import_from_path(req.package[i1], path = lib.path[i2]), silent = TRUE))
-            tempo.try[[i2]] <- suppressWarnings(try(reticulate::import_from_path(req.package[i1], path = lib.path[i2]), silent = TRUE)) # done twice to avoid the error message  about flushing present the first time but not the second time. see https://stackoverflow.com/questions/57357001/reticulate-1-13-error-in-sysstdoutflush-attempt-to-apply-non-function
-        }
-        if(all(sapply(tempo.try, FUN = grepl, pattern = "[Ee]rror"))){
-            print(tempo.try)
-            tempo.cat <- paste0("ERROR IN ", function.name, ": PACKAGE ", req.package[i1], " MUST BE INSTALLED IN THE MENTIONNED DIRECTORY:\n", paste(lib.path, collapse = "\n"))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-        } # else{
-        # suppressMessages(suppressWarnings(suppressPackageStartupMessages(assign(req.package[i1], reticulate::import(req.package[i1]))))) # not required because try() already evaluates
-        # }
-    }
 }
-
-
-################ Print / Exporting results (text & tables)
-
-
-######## fun_report() #### print string or data object into output file
-
-
-fun_report <- function(
-    data, 
-    output = "results.txt", 
-    path = "C:/Users/Gael/Desktop/", 
-    overwrite = FALSE, 
-    rownames.kept = FALSE, 
-    vector.cat = FALSE, 
-    noquote = TRUE, 
-    sep = 2
-){
-    # AIM
-    # log file function: print a character string or a data object into a same output file
-    # ARGUMENTS
-    # data: object to print in the output file. If NULL, nothing is done, with no warning
-    # output: name of the output file
-    # path: location of the output file
-    # overwrite: (logical) if output file already exists, defines if the printing is appended (default FALSE) or if the output file content is erased before printing (TRUE)
-    # rownames.kept: (logical) defines whether row names have to be removed or not in small tables (less than length.rows rows)
-    # vector.cat (logical). If TRUE print a vector of length > 1 using cat() instead of capture.output(). Otherwise (default FALSE) the opposite
-    # noquote: (logical). If TRUE no quote are present for the characters
-    # sep: number of separating lines after printed data (must be integer)
-    # RETURN
-    # nothing
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_report()
-    # fun_report(data = 1:3, output = "results.txt", path = "C:/Users/Gael/Desktop", overwrite = TRUE, rownames.kept = FALSE, vector.cat = FALSE, noquote = FALSE, sep = 2)
-    # DEBUGGING
-    # data = 1:3 ; output = "results.txt" ; path = "C:/Users/Gael/Desktop" ; overwrite = TRUE ; rownames.kept = FALSE ; vector.cat = FALSE ; noquote = FALSE ; sep = 2 # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # argument checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = output, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE & output == ""){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": output ARGUMENT AS \"\" DOES NOT CORRESPOND TO A VALID FILE NAME")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo <- fun_check(data = path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE){
-        if( ! all(dir.exists(path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-            tempo.cat <- paste0("ERROR IN ", function.name, ": path ARGUMENT DOES NOT CORRESPOND TO EXISTING DIRECTORY\n", paste(path, collapse = "\n"))
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = overwrite, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = rownames.kept, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = vector.cat, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = noquote, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = sep, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # the 4 next lines are inactivated but kept because at a time, I might have a problem with data (solved with data = NULL). These 4 lines are just to know how to detect a missing argument. Important here because if data is not provided, print the code of the data function
-    # arg.user.list <- as.list(match.call(expand.dots = FALSE))[-1] # recover all the arguments provided by the function user (excluding the argument with defaults values not provided by the user. Thus, it is really the list indicated by the user)
-    # default.arg.list <- formals(fun = sys.function(sys.parent())) # list of all the arguments of the function with their default values (not the values of the user !). It seems that ls() as first line of the function provide the names of the arguments (empty, called, etc., or not)
-    # arg.without.default.value <- sapply(default.arg.list, is.symbol) & sapply(sapply(default.arg.list, as.character), identical, "") # logical to detect argument without default values (these are typeof "symbol" and class "name" and empty character
-    # if( ! all(names(default.arg.list)[arg.without.default.value] %in% names(arg.user.list))){ # test that the arguments with no null values are provided by the user
-    # tempo.cat <- paste0("ERROR IN ", function.name, ": VALUE REQUIRED FOR THESE ARGUMENTS WITH NO DEFAULTS VALUES: ", paste(names(default.arg.list)[arg.without.default.value][ ! names(default.arg.list)[arg.without.default.value] %in% names(arg.user.list)], collapse = " "))
-    # stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    # }
-    # end argument checking
-    # main code
-    if( ! is.null(data)){
-        if(all(class(data) == "data.frame") | all(class(data) == "table") | all(class(data) %in% c("matrix", "array"))){ # before R4.0.0, it was  all(class(data) %in% c("matrix", "data.frame", "table"))
-            if(rownames.kept == FALSE & all(class(data) == "data.frame") & nrow(data) != 0 & nrow(data) <= 4){ # for data frames with nrows <= 4
-                rownames.output.tables <- ""
-                length.rows <- nrow(data)
-                for(i in 1:length.rows){ # replace the rownames of the first 4 rows by increasing number of spaces (because identical row names not allowed in data frames). This method cannot be extended to more rows as the printed data frame is shifted on the right because of "big empty rownames"
-                    rownames.output.tables <- c(rownames.output.tables, paste0(rownames.output.tables[i]," ", collapse=""))
-                }
-                row.names(data) <- rownames.output.tables[1:length.rows]
-            }else if(rownames.kept == FALSE & (all(class(data) == "table") | all(class(data) %in% c("matrix", "array")))){ # before R4.0.0, it was  & all(class(data) %in% c("matrix", "table"))
-                rownames(data) <- rep("", nrow(data)) # identical row names allowed in matrices and tables
-            }
-            if(noquote == TRUE){
-                utils::capture.output(noquote(data), file=paste0(path, "/", output), append = ! overwrite)
-            }else{
-                utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
-            }
-        }else if(is.vector(data) & all(class(data) != "list") & (length(data) == 1L | vector.cat == TRUE)){
-            if(noquote == TRUE){
-                cat(noquote(data), file= paste0(path, "/", output), append = ! overwrite)
-            }else{
-                cat(data, file= paste0(path, "/", output), append = ! overwrite)
-            }
-        }else if(all(base::mode(data) == "character")){ # characters (array, list, factor or vector with vector.cat = FALSE)
-            if(noquote == TRUE){
-                utils::capture.output(noquote(data), file=paste0(path, "/", output), append = ! overwrite)
-            }else{
-                utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
-            }
-        }else{ # other object (S4 for instance, which do not like noquote()
-            utils::capture.output(data, file=paste0(path, "/", output), append = ! overwrite)
-        }
-        sep.final <- paste0(rep("\n", sep), collapse = "")
-        write(sep.final, file= paste0(path, "/", output), append = TRUE) # add a sep
-    }
 }
+# end conversion of geom_hline and geom_vline
 
 
-######## fun_get_message() #### return error/warning/other messages of an expression (that can be exported)
 
 
-fun_get_message <- function(
-    data, 
-    kind = "error", 
-    header = TRUE, 
-    print.no = FALSE, 
-    text = NULL, 
-    env = NULL
-){
-    # AIM
-    # evaluate an instruction written between "" and return the first of the error, or warning or standard (non error non warning) messages if ever exist
-    # using argument print.no = FALSE, return NULL if no message, which is convenient in some cases
-    # WARNINGS
-    # Only the first message is returned
-    # Always use the env argument when fun_get_message() is used inside functions
-    # The function does not prevent printing if print() is used inside the instruction tested. To prevent that, use tempo <- capture.output(error <- fun_get_message(data = "fun_check(data = 'a', class = mean, neg.values = FALSE, print = TRUE)")). The return of fun_get_message() is assigned into error and the printed messages are captured by capture.output() and assigned into tempo. See the examples
-    # ARGUMENTS
-    # data: character string to evaluate
-    # kind: character string. Either "error" to get error messages, or "warning" to get warning messages, or "message" to get non error and non warning messages
-    # header: logical. Add a header in the returned message?
-    # print.no: logical. Print a message saying that no message reported?
-    # text: character string added to the output message (even if no message exists and print.no is TRUE). Inactivated if header is FALSE
-    # env: the name of an existing environment. NULL if not required
-    # RETURN
-    # the message or NULL if no message and print.no is FALSE
-    # REQUIRED PACKAGES
-    # none
-    # REQUIRED FUNCTIONS FROM CUTE_LITTLE_R_FUNCTION
-    # fun_check()
-    # EXAMPLES
-    # fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "error", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "warning", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)", kind = "message", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "wilcox.test()", kind = "error", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "sum(1)", kind = "error", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "message('ahah')", kind = "error", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "message('ahah')", kind = "message", print.no = TRUE, text = "IN A")
-    # fun_get_message(data = "ggplot2::ggplot(data = data.frame(X = 1:10, stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()", kind = "message", print.no = TRUE, text = "IN FUNCTION 1")
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; fun_get_message(data = 'fun_gg_boxplot(data = obs1, y = "Time", categ = "Group1")', kind = "message", print.no = TRUE, text = "IN FUNCTION 1")
-    # DEBUGGING
-    # data = "wilcox.test(c(1,1,3), c(1, 2, 4), paired = TRUE)" ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL # for function debugging
-    # data = "sum(1)" ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL  # for function debugging
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Group1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; data = 'fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Group1")' ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL  # for function debugging
-    # data = "message('ahah')" ; kind = "error" ; header = TRUE ; print.no = TRUE ; text = "IN A" ; env = NULL 
-    # data = 'ggplot2::ggplot(data = data.frame(X = "a", stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()' ; kind = "message" ; header = TRUE ; print.no = FALSE ; text = NULL # for function debugging
-    # data = 'ggplot2::ggplot(data = data.frame(X = "a", stringsAsFactors = TRUE), mapping = ggplot2::aes(x = X)) + ggplot2::geom_histogram()' ; kind = "warning" ; header = TRUE ; print.no = FALSE ; text = NULL # for function debugging
-    # data = "emmeans::emmeans(object = emm.rg, specs = contrast.var)" ; kind = "message" ; header = TRUE ; print.no = FALSE ; text = NULL ; env = NULL # for function debugging
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    # end function name
-    # required function checking
-    if(length(utils::find("fun_check", mode = "function")) == 0L){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": REQUIRED fun_check() FUNCTION IS MISSING IN THE R ENVIRONMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # no need to use reserved words to avoid bugs, because it is local, and  exists("tempo.warning", inherit = FALSE), never use the scope
-    # argument checking
-    # argument checking with fun_check()
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = kind, options = c("error", "warning", "message"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = print.no, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = header, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(text)){
-        tempo <- fun_check(data = text, class = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }
-    if( ! is.null(env)){
-        tempo <- fun_check(data = env, class = "environment", fun.name = function.name) ; eval(ee) #
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # end argument checking with fun_check()
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument checking
-    # main code
-    pdf(file = NULL) # send plots into a NULL file, no pdf file created
-    window.nb <- dev.cur()
-    invisible(dev.set(window.nb))
-    # last warning cannot be used because suppressWarnings() does not modify last.warning present in the base evironment (created at first warning in a new R session), or warnings() # to reset the warning history : unlockBinding("last.warning", baseenv()) ; assign("last.warning", NULL, envir = baseenv())
-    output <- NULL
-    tempo.error <- try(suppressMessages(suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))), silent = TRUE) # get error message, not warning or messages
-    if(any(class(tempo.error) %in% c("gg", "ggplot"))){
-        tempo.error <- try(suppressMessages(suppressWarnings(ggplot2::ggplot_build(tempo.error))), silent = TRUE)[1]
-    }
-    if(exists("tempo.error", inherit = FALSE) == TRUE){ # inherit = FALSE avoid the portee lexical and thus the declared word
-        if( ! all(class(tempo.error) == "try-error")){ # deal with NULL and S4 objects. Old code:  ! (all(class(tempo.error) == "try-error") & any(grepl(x = tempo.error, pattern = "^Error|^error|^ERROR"))) but problem with S4 objects. Old code : if((length(tempo.error) > 0 & ! any(grepl(x = tempo.error, pattern = "^Error|^error|^ERROR"))) | (length(tempo.error) == 0) ){ but problem when tempo.error is a list but added this did not work: | ! all(class(tempo.error) == "character")
-            tempo.error <- NULL
-        }
-    }else{
-        tempo.error <- NULL
-    }
-    if(kind == "error" & ! is.null(tempo.error)){ # 
-        if(header == TRUE){
-            tempo.error[1] <- gsub(x = tempo.error[1], pattern = "^Error i|^error i|^ERROR I", replacement = "I")
-            output <- paste0("ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.error[1]) #
-        }else{
-            output <- tempo.error[1] #
-        }
-    }else if(kind == "error" & is.null(tempo.error) & print.no == TRUE){
-        output <- paste0("NO ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-    }else if(kind != "error" & ( ! is.null(tempo.error)) & print.no == TRUE){
-        output <- paste0("NO ", ifelse(kind == "warning", "WARNING", "STANDARD (NON ERROR AND NON WARNING)"), " MESSAGE BECAUSE OF ERROR MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-    }else if(is.null(tempo.error)){
-        fun.warning.capture <- function(expr){
-            # from demo(error.catching) typed in the R console, coming from ?tryCatch
-            # see also http://mazamascience.com/WorkingWithData/?p=912
-            # return a character string or NULL
-            # expr <- wilcox.test.default(c(1, 1, 3), c(1, 2, 4), paired = TRUE)
-            W <- NULL
-            w.handler <- function(w){ # warning handler
-                W <<- w # send to the above env, i.e., the inside of the fun.warning.capture function
-                invokeRestart("muffleWarning") # here w.handler() muffles all the warnings. See http://romainfrancois.blog.free.fr/index.php?post/2009/05/20/Disable-specific-warnings to muffle specific warnings and print others
-            }
-            output <- list(
-                value = suppressMessages(withCallingHandlers(tryCatch(expr, error = function(e){e}), warning = w.handler)), # BEWARE: w.handler is a function written without (), like in other functions with FUN argument
-                warning = W # processed by w.handler()
-            )
-            return(if(is.null(output$warning)){NULL}else{as.character(output$warning)})
-        }
-        tempo.warn <- fun.warning.capture(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))
-        # warn.options.ini <- options()$warn ; options(warn = 1) ; tempo.warn <- utils::capture.output({tempo <- suppressMessages(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))}, type = "message") ; options(warn = warn.options.ini) # this recover warnings not messages and not errors but does not work in all enviroments
-        tempo.message <- utils::capture.output({
-            tempo <- suppressMessages(suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env})))
-            if(any(class(tempo) %in% c("gg", "ggplot"))){
-                tempo <- ggplot2::ggplot_build(tempo)
-            }else{
-                tempo <- suppressWarnings(eval(parse(text = data), envir = if(is.null(env)){parent.frame()}else{env}))
-            }
-        }, type = "message") # recover messages not warnings and not errors
-        if(kind == "warning" & ! is.null(tempo.warn)){
-            if(length(tempo.warn) > 0){ # to avoid character(0)
-                if( ! any(sapply(tempo.warn, FUN = "grepl", pattern = "() FUNCTION:$"))){
-                    tempo.warn <- paste(unique(tempo.warn), collapse = "\n") # if FALSE, means that the tested data is a special function. If TRUE, means that the data is a standard function. In that case, the output of capture.output() is two strings per warning messages: if several warning messages -> identical first string, which is removed in next messages by unique()
-                }else{
-                    tempo.warn <- paste(tempo.warn, collapse = "\n")
-                }
-                if(header == TRUE){
-                    if(any(grepl(x = tempo.warn[[1]], pattern = "^simpleWarning i"))){
-                        tempo.warn[[1]] <- gsub(x = tempo.warn[[1]], pattern = "^Warning i", replacement = "I")
-                    }
-                    if(any(grepl(x = tempo.warn[[1]], pattern = "^Warning i"))){
-                        tempo.warn[[1]] <- gsub(x = tempo.warn[[1]], pattern = "^Warning i", replacement = "I")
-                    }
-                    output <- paste0("WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.warn) #
-                }else{
-                    output <- tempo.warn #
-                }
-            }else{
-                if(print.no == TRUE){
-                    output <- paste0("NO WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-                } # no need else{} here because output is already NULL at first
-            }
-        }else if(kind == "warning" & is.null(tempo.warn) & print.no == TRUE){
-            output <- paste0("NO WARNING MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-        }else if(kind == "message" & exists("tempo.message", inherit = FALSE) == TRUE){ # inherit = FALSE avoid the portee lexical and thus the declared word
-            if(length(tempo.message) > 0){ # if something is returned by capture.ouptput() (only in this env) with a length more than 1
-                if(header == TRUE){
-                    output <- paste0("STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text, ":\n", tempo.message) #
-                }else{
-                    output <- tempo.message #
-                }
-            }else{
-                if(print.no == TRUE){
-                    output <- paste0("NO STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-                } # no need else{} here because output is already NULL at first
-            }
-        }else if(kind == "message" & exists("tempo.message", inherit = FALSE) == FALSE & print.no == TRUE){
-            output <- paste0("NO STANDARD (NON ERROR AND NON WARNING) MESSAGE REPORTED", ifelse(is.null(text), "", " "), text)
-        } # no need else{} here because output is already NULL at first
-    } # no need else{} here because output is already NULL at first
-    invisible(dev.off(window.nb)) # end send plots into a NULL file
-    return(output) # do not use cat() because the idea is to reuse the message
+# kind of geom_point (vectorial or raster)
+scatter.kind <- vector("list", length = length(data1)) # list of same length as data1, that will be used to use either ggplot2::geom_point() (vectorial dot layer) or fun_gg_point_rast() (raster dot layer)
+fix.ratio <- FALSE
+if(is.null(raster.threshold)){
+if(raster == TRUE){
+scatter.kind[] <- "fun_gg_point_rast" # not important to fill everything: will be only used when geom == "geom_point"
+fix.ratio <- TRUE
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") RASTER PLOT GENERATED -> ASPECT RATIO OF THE PLOT REGION SET BY THE raster.ratio ARGUMENT (", fun_round(raster.ratio, 2), ") TO AVOID A BUG OF ELLIPSOID DOT DRAWING")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}else{
+scatter.kind[] <- "ggplot2::geom_point"
 }
-
-
-
-
-
-# Error: class order not good when a class is removed due to NA
-# Error: line 136 in check 20201126 with add argument
-# Solve this: sometimes error messages can be more than the max display (8170). Thus, check every paste0("ERROR IN ", function.name, and trunck the message if to big. In addition, add at the begining of the warning message that it is too long and see the $warn output for complete message. Add also this into fun_scatter
-# add dot.shape ? See with available aesthetic layers
-# rasterise: https://cran.r-project.org/web/packages/ggrastr/vignettes/Raster_geoms.html
-# add horizontal argument and deal any conflict with vertical argument. Start with horizontal = NULL as default. If ! is.null() -> convert vertical if required
-
-fun_gg_boxplot <- function(
-    data1, 
-    y, 
-    categ, 
-    categ.class.order = NULL, 
-    categ.color = NULL, 
-    box.legend.name = NULL, 
-    box.fill = FALSE, 
-    box.width = 0.5, 
-    box.space = 0.1, 
-    box.line.size = 0.75, 
-    box.notch = FALSE, 
-    box.alpha = 1, 
-    box.mean = TRUE, 
-    box.whisker.kind = "std", 
-    box.whisker.width = 0, 
-    dot.color = grey(0.25), 
-    dot.categ = NULL, 
-    dot.categ.class.order = NULL, 
-    dot.legend.name = NULL, 
-    dot.tidy = FALSE, 
-    dot.tidy.bin.nb = 50, 
-    dot.jitter = 0.5, 
-    dot.seed = 2, 
-    dot.size = 3, 
-    dot.alpha = 0.5, 
-    dot.border.size = 0.5, 
-    dot.border.color = NULL, 
-    x.lab = NULL, 
-    x.angle = 0, 
-    y.lab = NULL, 
-    y.lim = NULL, 
-    y.log = "no", 
-    y.tick.nb = NULL, 
-    y.second.tick.nb = 1, 
-    y.include.zero = FALSE, 
-    y.top.extra.margin = 0.05, 
-    y.bottom.extra.margin = 0.05, 
-    stat.pos = "top", 
-    stat.mean = FALSE, 
-    stat.size = 4, 
-    stat.dist = 5, 
-    stat.angle = 0, 
-    vertical = TRUE, 
-    text.size = 12, 
-    title = "", 
-    title.text.size = 8, 
-    legend.show = TRUE, 
-    legend.width = 0.5, 
-    article = TRUE, 
-    grid = FALSE, 
-    add = NULL, 
-    return = FALSE, 
-    return.ggplot = FALSE,
-    return.gtable = TRUE,
-    plot = TRUE, 
-    warn.print = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # Plot ggplot2 boxplots + dots + means
-    # For ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
-    # WARNINGS
-    # Rows containing NA in data1[, c(y, categ)] will be removed before processing, with a warning (see below)
-    # Hinges are not computed like in the classical boxplot() function of R. See https://ggplot2.tidyverse.org/reference/geom_boxplot.html
-    # To have a single box, please create a factor column with a single class and specify the name of this column in the categ argument. For a single set of grouped boxes, create a factor column with a single class and specify this column in categ argument as first element (i.e., as categ1, knowing that categ2 must also be specified in this situation). See categ argument below
-    # The dot.alpha argument can alter the display of the color boxes when using pdf output
-    # Size arguments (box.line.size, dot.size, dot.border.size, stat.size, text.size and title.text.size) are in mm. See Hadley comment in https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size. See also http://sape.inf.usi.ch/quick-reference/ggplot2/size). Unit object are not accepted, but conversion can be used (e.g., grid::convertUnit(grid::unit(0.2, "inches"), "mm", valueOnly = TRUE))
-    # Display seems to be done twice on Windows devices (like a blink). However, no double plots on pdf devices. Thus, the blink remains mysterious
-    # To remove boxes and have only dots, use box.alpha = 0
-    # ARGUMENTS
-    # data1: data frame containing one column of quantitative values (see the y argument below) and one or two columns of categories (see the categ argument below). Duplicated column names are not allowed
-    # y: character string of the data1 column name for y-axis (column containing numeric values). Numeric values will be split according to the classes of the column names indicated in the categ argument to generate the boxes and will also be used to plot the dots
-    # categ: vector of character strings of the data1 column name for categories (column of characters or factors). Must be either one or two column names. If a single column name (further referred to as categ1), then one box per class of categ1. If two column names (further referred to as categ1 and categ2), then one box per class of categ2, which form a group of boxes in each class of categ1. WARNING: no empty classes allowed. To have a single box, create a factor column with a single class and specify the name of this column in the categ argument (here, no categ2 in categ argument). For a single set of grouped boxes, create a factor column with a single class and specify this column in categ argument as first element (i.e., as categ1), in addition to the already used category (as categ2 in this situation)
-    # categ.class.order: list indicating the order of the classes of categ1 and categ2 represented on the boxplot (the first compartment for categ1 and and the second for categ2). If categ.class.order == NULL, classes are represented according to the alphabetical order. Some compartments can be NULL and others not. See the categ argument for categ1 and categ2 description
-    # categ.color: vector of color character string for box frames (see the categ argument for categ1 and categ2 description)
-    # If categ.color == NULL, default colors of ggplot2, whatever categ1 and categ2
-    # If categ.color is non-null and only categ1 in categ argument, categ.color can be either:
-    # (1) a single color string. All the boxes will have this color, whatever the number of classes of categ1
-    # (2) a vector of string colors, one for each class of categ1. Each color will be associated according to categ.class.order of categ1
-    # (3) a vector or factor of string colors, like if it was one of the column of data1 data frame. WARNING: a single color per class of categ1 and a single class of categ1 per color must be respected
-    # Color functions, like grey(), hsv(), etc., are also accepted
-    # Positive integers are also accepted instead of character strings, as long as above rules about length are respected. Integers will be processed by fun_gg_palette() using the maximal integer value among all the integers in categ.color (see fun_gg_palette())
-    # If categ.color is non-null and categ1 and categ2 are specified, all the rules described above will apply to categ2 instead of categ1 (colors will be determined for boxes inside a group of boxes)
-    # box.legend.name: character string of the legend title. If box.legend.name is NULL, then box.legend.name <- categ1 if only categ1 is present, and box.legend.name <- categ2 if categ1 and categ2 are present in the categ argument. Write "" if no legend required. See the categ argument for categ1 and categ2 description
-    # box.fill: logical. Fill the box? If TRUE, the categ.color argument will be used to generate filled boxplots (the box frames being black) as well as filled outlier dots (the dot border being controlled by the dot.border.color argument). If all the dots are plotted (argument dot.color other than NULL), they will be over the boxes. If FALSE, the categ.color argument will be used to color the box frames and the outlier dot borders. If all the dots are plotted, they will be beneath the boxes
-    # box.width: single numeric value (from 0 to 1) of width of either boxes or group of boxes
-    # When categ argument has a single categ1 element (i.e., separate boxes. See the categ argument for categ1 and categ2 description), then each class of categ1 is represented by a single box. In that case, box.width argument defines each box width, from 0 (no box width) to 1 (max box width), but also the space between boxes (the code uses 1 - box.width for the box spaces). Of note, xmin and xmax of the fun_gg_boxplot() output report the box boundaries (around x-axis unit 1, 2, 3, etc., for each box)
-    # When categ argument has a two categ1 and categ2 elements (i.e., grouped boxes), box.width argument defines the width allocated for each set of grouped boxes, from 0 (no group width) to 1 (max group width), but also the space between grouped boxes (the code uses 1 - box.width for the spaces). Of note, xmin and xmax of the fun_gg_boxplot() output report the box boundaries (around x-axis unit 1, 2, 3, etc., for each set of grouped box)
-    # box.space: single numeric value (from 0 to 1) indicating the box separation inside grouped boxes, when categ argument has a two categ1 and categ2 elements. 0 means no space and 1 means boxes shrunk to a vertical line. Ignored if categ argument has a single categ1 element
-    # box.line.size: single numeric value of line width of boxes and whiskers in mm
-    # box.notch: logical. Notched boxplot? It TRUE, display notched boxplot, notches corresponding approximately to the 95% confidence interval of the median (the notch interval is exactly 1.58 x Inter Quartile Range (IQR) / sqrt(n), with n the number of values that made the box). If notch intervals between two boxes do not overlap, it can be interpreted as significant median differences
-    # box.alpha: single numeric value (from 0 to 1) of box transparency (full transparent to full opaque, respectively). To remove boxplots, use box.alpha = 0
-    # box.mean: logical. Add mean value? If TRUE, a diamond-shaped dot, with the horizontal diagonal corresponding to the mean value, is displayed over each boxplot
-    # box.whisker.kind: range of the whiskers. Either "no" (no whiskers), or "std" (length of each whisker equal to 1.5 x Inter Quartile Range (IQR)), or "max" (length of the whiskers up or down to the most distant dot)
-    # box.whisker.width: single numeric value (from 0 to 1) of the whisker width, with 0 meaning no whiskers and 1 meaning a width equal to the box width
-    # dot.color: vector of color character string ruling the dot colors and the dot display. See the example section below for easier understanding of the rules described here
-    # If NULL, no dots plotted
-    # If "same", the dots will have the same colors as the respective boxplots
-    # Otherwise, as in the rule (1), (2) or (3) described in the categ.color argument, except that in the possibility (3), the rule "a single color per class of categ and a single class of categ per color", does not have to be respected (for instance, each dot can have a different color). Colors will also depend on the dot.categ argument. If dot.categ is NULL, then colors will be applied to each class of the last column name specified in categ. If dot.categ is non-NULL, colors will be applied to each class of the column name specified in dot.categ. See examples
-    # dot.categ: optional single character string of a column name (further referred to as categ3) of the data1 argument. This column of data1 will be used to generate a legend for dots, in addition to the legend for boxes. See the dot.color argument for details about the way the legend is built using the two dot.categ and dot.color arguments. If NULL, no legend created and the colors of dots will depend on dot.color and categ arguments (as explained in the dot.color argument)
-    # dot.categ.class.order: optional vector of character strings indicating the order of the classes of categ3 (see the dot.categ argument). If dot.categ is non-NULL and dot.categ.class.order is NULL, classes are displayed in the legend according to the alphabetical order. Ignored if dot.categ is NULL
-    # dot.legend.name: optional character string of the legend title for categ3 (see the dot.categ argument). If dot.legend.name == NULL, dot.categ value is used (name of the column in data1). Write "" if no legend required. Ignored if dot.categ is NULL
-    # dot.tidy: logical. Nice dot spreading? If TRUE, use the geom_dotplot() function for a nice representation. WARNING: change the true quantitative coordinates of dots (i.e., y-axis values for vertical display) because of binning. Thus, the gain in aestheticism is associated with a loss in precision that can be very important. If FALSE, dots are randomly spread on the qualitative axis, using the dot.jitter argument (see below) keeping the true quantitative coordinates
-    # dot.tidy.bin.nb: positive integer indicating the number of bins (i.e., nb of separations) of the y.lim range. Each dot will then be put in one of the bin, with a diameter of the width of the bin. In other words, increase the number of bins to have smaller dots. Not considered if dot.tidy is FALSE
-    # dot.jitter: numeric value (from 0 to 1) of random dot horizontal dispersion (for vertical display), with 0 meaning no dispersion and 1 meaning dispersion in the corresponding box width interval. Not considered if dot.tidy is TRUE
-    # dot.seed: integer value that set the random seed. Using the same number will generate the same dot jittering. Write NULL to have different jittering each time the same instruction is run. Ignored if dot.tidy is TRUE
-    # dot.size: numeric value of dot diameter in mm. Not considered if dot.tidy is TRUE
-    # dot.alpha: numeric value (from 0 to 1) of dot transparency (full transparent to full opaque, respectively)
-    # dot.border.size: numeric value of border dot width in mm. Write zero for no dot border. If dot.tidy is TRUE, value 0 remove the border and other values leave the border without size control (geom_doplot() feature)
-    # dot.border.color: single character color string defining the color of the dot border (same color for all the dots, whatever their categories). If dot.border.color == NULL, the border color will be the same as the dot color. A single integer is also accepted instead of a character string, that will be processed by fun_gg_palette()
-    # x.lab: a character string or expression for x-axis legend. If NULL, character string of categ1 (see the categ argument for categ1 and categ2 description)
-    # x.angle: integer value of the text angle for the x-axis numbers, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
-    # y.lab: a character string or expression for y-axis legend. If NULL, character string of the y argument
-    # y.lim: 2 numeric values indicating the range of the y-axis. Order matters (for inverted axis). If NULL, the range of the x column name of data1 will be used. 
-    # y.log: either "no", "log2" (values in the y argument column of the data1 data frame will be log2 transformed and y-axis will be log2 scaled) or "log10" (values in the y argument column of the data1 data frame will be log10 transformed and y-axis will be log10 scaled). WARNING: not possible to have horizontal boxes with a log axis, due to a bug in ggplot2 (see https://github.com/tidyverse/ggplot2/issues/881)
-    # y.tick.nb: approximate number of desired values labeling the y-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if y.log is "no", then the number of labeling values is set by ggplot2. If NULL and if y.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the y.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for y.lim = c(9, 1200)). WARNING: if non-NULL and if y.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
-    # y.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if y.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$y.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
-    # y.include.zero: logical. Does y.lim range include 0? Ignored if y.log is "log2" or "log10"
-    # y.top.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to y.lim. If different from 0, add the range of the axis multiplied by y.top.extra.margin (e.g., abs(y.lim[2] - y.lim[1]) * y.top.extra.margin) to the top of y-axis
-    # y.bottom.extra.margin: idem as y.top.extra.margin but to the bottom of y-axis
-    # stat.pos: add the median number above the corresponding box. Either NULL (no number shown), "top" (at the top of the plot region) or "above" (above each box)
-    # stat.mean: logical. Display mean numbers instead of median numbers? Ignored if stat.pos is NULL
-    # stat.size: numeric value of the stat font size in mm. Ignored if stat.pos is NULL
-    # stat.dist: numeric value of the stat distance in percentage of the y-axis range (stat.dist = 5 means move the number displayed at 5% of the y-axis range). Ignored if stat.pos is NULL or "top"
-    # stat.angle: integer value of the angle of stat, using the same rules as in ggplot2. Positive values for counterclockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Negative values for clockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
-    # vertical: logical. Vertical boxes? WARNING: will be automatically set to TRUE if y.log argument is other than "no". Indeed, not possible to have horizontal boxes with a log axis, due to a bug in ggplot2 (see https://github.com/tidyverse/ggplot2/issues/881)
-    # text.size: numeric value of the font size of the (1) axis numbers, (2) axis labels and (3) texts in the graphic legend (in mm)
-    # title: character string of the graph title
-    # title.text.size: numeric value of the title font size in mm
-    # legend.show: logical. Show legend? Not considered if categ argument is NULL, because this already generate no legend, excepted if legend.width argument is non-NULL. In that specific case (categ is NULL, legend.show is TRUE and legend.width is non-NULL), an empty legend space is created. This can be useful when desiring graphs of exactly the same width, whatever they have legends or not
-    # legend.width: single proportion (between 0 and 1) indicating the relative width of the legend sector (on the right of the plot) relative to the width of the plot. Value 1 means that the window device width is split in 2, half for the plot and half for the legend. Value 0 means no room for the legend, which will overlay the plot region. Write NULL to inactivate the legend sector. In such case, ggplot2 will manage the room required for the legend display, meaning that the width of the plotting region can vary between graphs, depending on the text in the legend
-    # article: logical. If TRUE, use an article theme (article like). If FALSE, use a classic related ggplot theme. Use the add argument (e.g., add = "+ggplot2::theme_classic()" for the exact classic ggplot theme
-    # grid: logical. Draw lines in the background to better read the box values? Not considered if article == FALSE (grid systematically present)
-    # add: character string allowing to add more ggplot2 features (dots, lines, themes, facet, etc.). Ignored if NULL
-    # WARNING: (1) the string must start with "+", (2) the string must finish with ")" and (3) each function must be preceded by "ggplot2::". Example: "+ ggplot2::coord_flip() + ggplot2::theme_bw()"
-    # If the character string contains the "ggplot2::theme" string, then the article argument of fun_gg_boxplot() (see above) is ignored with a warning. In addition, some arguments can be overwritten, like x.angle (check all the arguments)
-    # Handle the add argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
-    # WARNING: the call of objects inside the quotes of add can lead to an error if the name of these objects are some of the fun_gg_boxplot() arguments. Indeed, the function will use the internal argument instead of the global environment object. Example article <- "a" in the working environment and add = '+ ggplot2::ggtitle(article)'. The risk here is to have TRUE as title. To solve this, use add = '+ ggplot2::ggtitle(get("article", envir = .GlobalEnv))'
-    # return: logical. Return the graph parameters?
-    # return.ggplot: logical. Return the ggplot object in the output list? Ignored if return argument is FALSE. WARNING: always assign the fun_gg_boxplot() function (e.g., a <- fun_gg_boxplot()) if return.ggplot argument is TRUE, otherwise, double plotting is performed. See $ggplot in the RETURN section below for more details
-    # return.gtable: logical. Return the ggplot object as gtable of grobs in the output list? Ignored if plot argument is FALSE. Indeed, the graph must be plotted to get the grobs dispositions. See $gtable in the RETURN section below for more details
-    # plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
-    # warn.print: logical. Print warnings at the end of the execution? ? If FALSE, warning messages are never printed, but can still be recovered in the returned list. Some of the warning messages (those delivered by the internal ggplot2 functions) are not apparent when using the argument plot = FALSE
-    # lib.path: character string indicating the absolute path of the required packages (see below). if NULL, the function will use the R library default folders
-    # RETURN
-    # A boxplot if plot argument is TRUE
-    # A list of the graph info if return argument is TRUE:
-    # $data: the initial data with graphic information added
-    # $stat: the graphic statistics (mostly equivalent to ggplot_build()$data[[2]])
-    # $removed.row.nb: which rows have been removed due to NA/Inf detection in y and categ columns (NULL if no row removed)
-    # $removed.rows: removed rows (NULL if no row removed)
-    # $plot: the graphic box and dot coordinates
-    # $dots: dot coordinates
-    # $main.box: coordinates of boxes
-    # $median: median coordinates
-    # $sup.whisker: coordinates of top whiskers (y for base and y.end for extremities)
-    # $inf.whisker: coordinates of bottom whiskers (y for base and y.end for extremities)
-    # $sup.whisker.edge: coordinates of top whisker edges (x and xend)
-    # $inf.whisker.edge: coordinates of bottom whisker edges(x and xend)
-    # $mean: diamond mean coordinates (only if box.mean argument is TRUE)
-    # $stat.pos: coordinates of stat numbers (only if stat.pos argument is not NULL)
-    # y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non-NULL or if y.log argument is different from "no")
-    # y.second.tick.values: values of secondary ticks. NULL except if y.second.tick.nb argument is non-NULL or if y.log argument is different from "no")
-    # $panel: the variable names used for the panels (NULL if no panels). WARNING: NA can be present according to ggplot2 upgrade to v3.3.0
-    # $axes: the x-axis and y-axis info
-    # $warn: the warning messages. Use cat() for proper display. NULL if no warning. WARNING: warning messages delivered by the internal ggplot2 functions are not apparent when using the argument plot = FALSE
-    # $ggplot: ggplot object that can be used for reprint (use print(...$ggplot) or update (use ...$ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Of note, a non-NULL $ggplot in the output list is sometimes annoying as the manipulation of this list prints the plot
-    # $gtable: gtable object that can be used for reprint (use gridExtra::grid.arrange(...$ggplot) or with additionnal grobs (see the grob decomposition in the examples). NULL if return.ggplot argument is FALSE. Contrary to $ggplot, a non-NULL $gtable in the output list is not annoying as the manipulation of this list does not print the plot
-    # REQUIRED PACKAGES
-    # ggplot2
-    # gridExtra
-    # lemon (in case of use in the add argument)
-    # scales
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # fun_check()
-    # fun_comp_1d()
-    # fun_comp_2d()
-    # fun_gg_just()
-    # fun_gg_palette()
-    # fun_inter_ticks()
-    # fun_name_change()
-    # fun_pack()
-    # fun_round()
-    # fun_scale()
-    # EXAMPLE
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(20, 100, 10), rnorm(20, 200, 50), rnorm(20, 500, 60), rnorm(20, 100, 50)), Categ1 = rep(c("CAT", "DOG"), times = 40), Categ2 = rep(c("A", "B", "C", "D"), each = 20), Color1 = rep(c("coral", "lightblue"), times = 40), Color2 = rep(c("#9F2108", "#306100", "#007479", "#8500C0"), each = 20), stringsAsFactors = TRUE) ; set.seed(NULL) ; fun_gg_boxplot(data1 = obs1, y = "Time", categ = "Categ1")
-    # see http
-    # DEBUGGING
-    # set.seed(1) ; obs1 <- data.frame(Time = c(rnorm(10), rnorm(10) + 2), Categ1 = rep(c("G", "H"), each = 10), stringsAsFactors = TRUE) ; set.seed(NULL) ; obs1$Time[1:10] <- NA ; data1 = obs1 ; y = "Time" ; categ = c("Categ1") ; categ.class.order = NULL ; categ.color = NULL ; box.legend.name = NULL ; box.fill = FALSE ; box.width = 0.5 ; box.space = 0.1 ; box.line.size = 0.75 ; box.notch = FALSE ; box.alpha = 1 ; box.mean = TRUE ; box.whisker.kind = "std" ; box.whisker.width = 0 ; dot.color = grey(0.25) ; dot.categ = NULL ; dot.categ.class.order = NULL ; dot.legend.name = NULL ; dot.tidy = FALSE ; dot.tidy.bin.nb = 50 ; dot.jitter = 0.5 ; dot.seed = 2 ; dot.size = 3 ; dot.alpha = 0.5 ; dot.border.size = 0.5 ; dot.border.color = NULL ; x.lab = NULL ; x.angle = 0 ; y.lab = NULL ; y.lim = NULL ; y.log = "no" ; y.tick.nb = NULL ; y.second.tick.nb = 1 ; y.include.zero = FALSE ; y.top.extra.margin = 0.05 ; y.bottom.extra.margin = 0.05 ; stat.pos = "top" ; stat.mean = FALSE ; stat.size = 4 ; stat.dist = 5 ; stat.angle = 0 ; vertical = TRUE ; text.size = 12 ; title = "" ; title.text.size = 8 ; legend.show = TRUE ; legend.width = 0.5 ; article = TRUE ; grid = FALSE ; add = NULL ; return = FALSE ; return.ggplot = FALSE ; return.gtable = TRUE ; plot = TRUE ; warn.print = FALSE ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots = FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots = FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_comp_2d", 
-        "fun_gg_just", 
-        "fun_gg_palette", 
-        "fun_name_change", 
-        "fun_pack", 
-        "fun_check", 
-        "fun_round", 
-        "fun_scale",
-        "fun_inter_ticks"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function")) == 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words to avoid bugs (names of dataframe columns used in this function)
-    reserved.words <- c("categ.check", "categ.color", "dot.color", "dot.categ", "dot.max", "dot.min", "group", "PANEL", "group.check", "MEAN", "tempo.categ1", "tempo.categ2", "text.max.pos", "text.min.pos", "x", "x.y", "y", "y.check", "y_from.dot.max", "ymax", "tidy_group", "binwidth")
-    # end reserved words to avoid bugs (used in this function)
-    # arg with no default values
-    mandat.args <- c(
-        "data1", 
-        "y", 
-        "categ"
-    )
-    tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), ")")))
-    if(any(tempo)){ # normally no NA for missing() output
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", "HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = categ, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    if( ! is.null(categ.class.order)){
-        tempo <- fun_check(data = categ.class.order, class = "list", fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = categ.class.order, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(box.legend.name)){
-        tempo <- fun_check(data = box.legend.name, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = box.legend.name, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(categ.color)){
-        tempo1 <- fun_check(data = categ.color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-        tempo2 <- fun_check(data = categ.color, class = "factor", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.check.color <- fun_check(data = categ.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, neg.values = FALSE, fun.name = function.name)$problem
-            if(tempo.check.color == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(any(categ.color == 0L, na.rm = TRUE)){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = categ.color, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = box.fill, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.space, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.line.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.notch, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.alpha, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.mean, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.whisker.kind, options = c("no", "std", "max"), length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = box.whisker.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(dot.color)){
-        tempo1 <- fun_check(data = dot.color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-        tempo2 <- fun_check(data = dot.color, class = "factor", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.check.color <- fun_check(data = dot.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, neg.values = FALSE, fun.name = function.name)$problem
-            if(tempo.check.color == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }else if(any(dot.color == 0L, na.rm = TRUE)){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE A FACTOR OR CHARACTER VECTOR OR POSITVE INTEGER VECTOR") # integer possible because dealt above
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.color, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(dot.categ)){
-        tempo <- fun_check(data = dot.categ, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.categ, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(dot.categ.class.order)){
-        tempo <- fun_check(data = dot.categ.class.order, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.categ.class.order, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(dot.legend.name)){
-        tempo <- fun_check(data = dot.legend.name, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.legend.name, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = dot.tidy, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dot.tidy.bin.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if(tempo$problem == FALSE){
-        if(dot.tidy.bin.nb == 0L){ # length and NA checked above
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.tidy.bin.nb ARGUMENT MUST BE A NON-NULL AND POSITVE INTEGER VALUE") # integer possible because dealt above
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }
-    tempo <- fun_check(data = dot.jitter, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(dot.seed)){
-        tempo <- fun_check(data = dot.seed, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.seed, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = dot.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dot.alpha, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = dot.border.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(dot.border.color)){
-        tempo1 <- fun_check(data = dot.border.color, class = "vector", mode = "character", length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.border.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR STRING STARTING BY #, OR (2) A COLOR NAME GIVEN BY colors(), OR (3) AN INTEGER VALUE")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }else if(tempo1$problem == FALSE & tempo2$problem == TRUE){
-            if( ! all(dot.border.color %in% colors() | grepl(pattern = "^#", dot.border.color), na.rm = TRUE)){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.border.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR STRING STARTING BY #, OR (2) A COLOR NAME GIVEN BY colors(), OR (3) AN INTEGER VALUE")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.border.color, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(x.lab)){
-        tempo1 <- fun_check(data = x.lab, class = "expression", length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = x.lab,  class = "vector", mode = "character", length = 1, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lab ARGUMENT MUST BE A SINGLE CHARACTER STRING OR EXPRESSION")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x.lab, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = x.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(y.lab)){
-        tempo1 <- fun_check(data = y.lab, class = "expression", length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = y.lab,  class = "vector", mode = "character", length = 1, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lab ARGUMENT MUST BE A SINGLE CHARACTER STRING OR EXPRESSION")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.lab, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(y.lim)){
-        tempo <- fun_check(data = y.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if(any(is.infinite(y.lim))){ # normally no NA for is.infinite() output
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.lim, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = y.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(y.tick.nb)){
-        tempo <- fun_check(data = y.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if(y.tick.nb < 0){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ny.tick.nb ARGUMENT MUST BE A NON NULL POSITIVE INTEGER")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(y.second.tick.nb)){
-        tempo <- fun_check(data = y.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if(y.second.tick.nb <= 0){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ny.second.tick.nb ARGUMENT MUST BE A NON NULL POSITIVE INTEGER")
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.second.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = y.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.top.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.bottom.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(stat.pos)){
-        tempo <- fun_check(data = stat.pos, options = c("top", "above"), length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = stat.pos, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = stat.mean, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = stat.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = stat.dist, class = "vector", mode = "numeric", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = stat.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = vertical, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = legend.show, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(legend.width)){
-        tempo <- fun_check(data = legend.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = legend.width, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = article, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = grid, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(add)){
-        tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = add, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.ggplot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.gtable, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path), na.rm = TRUE)){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nDIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = lib.path, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if(any(arg.check) == TRUE){ # normally no NA
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between == #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length) == 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){ # normally no NA because is.na() used here
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "data1", 
-        "y", 
-        "categ", 
-        "box.fill", 
-        "box.width", 
-        "box.space", 
-        "box.line.size", 
-        "box.notch", 
-        "box.alpha", 
-        "box.mean", 
-        "box.whisker.kind", 
-        "box.whisker.width", 
-        # "dot.color", # inactivated because can be null
-        "dot.tidy", 
-        "dot.tidy.bin.nb", 
-        "dot.jitter", 
-        # "dot.seed", # inactivated because can be null
-        "dot.size", 
-        "dot.alpha", 
-        "dot.border.size", 
-        "x.angle", 
-        "y.log", 
-        # "y.second.tick.nb", # inactivated because can be null
-        "y.include.zero", 
-        "y.top.extra.margin", 
-        "y.bottom.extra.margin", 
-        # "stat.pos", # inactivated because can be null
-        "stat.mean", 
-        "stat.size", 
-        "stat.dist", 
-        "stat.angle", 
-        "vertical", 
-        "text.size", 
-        "title", 
-        "title.text.size", 
-        "legend.show", 
-        # "legend.width", # inactivated because can be null
-        "article", 
-        "grid", 
-        "return", 
-        "return.ggplot", 
-        "return.gtable", 
-        "plot", 
-        "warn.print"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){# normally no NA with is.null()
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # see also Protocol 100-rev0 Parallelization in R.docx
-    if(exists(".Random.seed", envir = .GlobalEnv)){ # if .Random.seed does not exists, it means that no random operation has been performed yet in any R environment
-        tempo.random.seed <- .Random.seed
-        on.exit(assign(".Random.seed", tempo.random.seed, env = .GlobalEnv))
-    }else{
-        on.exit(set.seed(NULL)) # inactivate seeding -> return to complete randomness
-    }
-    set.seed(dot.seed)
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    # end warning initiation
-    # other checkings
-    if(any(duplicated(names(data1)), na.rm = TRUE)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nDUPLICATED COLUMN NAMES OF data1 ARGUMENT NOT ALLOWED:\n", paste(names(data1)[duplicated(names(data1))], collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! (y %in% names(data1))){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\ny ARGUMENT MUST BE A COLUMN NAME OF data1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        tempo <- fun_check(data = data1[, y], data.name = "y COLUMN OF data1", class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny ARGUMENT MUST BE NUMERIC COLUMN IN data1")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(length(categ) > 2){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg ARGUMENT CANNOT HAVE MORE THAN 2 COLUMN NAMES OF data1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if( ! all(categ %in% names(data1))){ # all() without na.rm -> ok because categ cannot be NA (tested above)
-        tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg ARGUMENT MUST BE COLUMN NAMES OF data1. HERE IT IS:\n", paste(categ, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(length(dot.categ) > 1){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT CANNOT HAVE MORE THAN 1 COLUMN NAMES OF data1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else if( ! all(dot.categ %in% names(data1))){ # all() without na.rm -> ok because dot.categ cannot be NA (tested above)
-        tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT MUST BE COLUMN NAMES OF data1. HERE IT IS:\n", paste(dot.categ, collapse = " "))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # reserved word checking
-    if(any(names(data1) %in% reserved.words, na.rm = TRUE)){
-        if(any(duplicated(names(data1)), na.rm = TRUE)){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nDUPLICATED COLUMN NAMES OF data1 ARGUMENT NOT ALLOWED:\n", paste(names(data1)[duplicated(names(data1))], collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if( ! is.null(dot.categ)){
-            if(dot.categ %in% categ){
-                reserved.words <- c(reserved.words, paste0(dot.categ, "_DOT")) # paste0(dot.categ, "_DOT") is added to the reserved words because in such situation, a new column will be added to data1 that is named paste0(dot.categ, "_DOT")
-            }
-        }
-        tempo.output <- fun_name_change(names(data1), reserved.words)
-        for(i2 in 1:length(tempo.output$ini)){ # a loop to be sure to take the good ones
-            names(data1)[names(data1) == tempo.output$ini[i2]] <- tempo.output$post[i2]
-            if(any(y == tempo.output$ini[i2])){ # any() without na.rm -> ok because y cannot be NA (tested above)
-                y[y == tempo.output$ini[i2]] <- tempo.output$post[i2]
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN y ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN y ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # WARNING: names of y argument potentially replaced
-            if(any(categ == tempo.output$ini[i2])){ # any() without na.rm -> ok because categ cannot be NA (tested above)
-                categ[categ == tempo.output$ini[i2]] <- tempo.output$post[i2]
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN categ ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN categ ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # WARNING: names of categ argument potentially replaced
-            if( ! is.null(dot.categ)){
-                if(any(dot.categ == tempo.output$ini[i2])){ # any() without na.rm -> ok because dot.categ cannot be NA (tested above)
-                    dot.categ[dot.categ == tempo.output$ini[i2]] <- tempo.output$post[i2]
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN dot.categ ARGUMENT (COLUMN NAMES OF data1 ARGUMENT),\n", tempo.output$ini[i2], " HAS BEEN REPLACED BY ", tempo.output$post[i2], "\nBECAUSE RISK OF BUG AS SOME NAMES IN dot.categ ARGUMENT ARE RESERVED WORD USED BY THE ", function.name, " FUNCTION")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            # WARNING: names of dot.categ argument potentially replaced
-        }
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") REGARDING COLUMN NAMES REPLACEMENT, THE NAMES\n", paste(tempo.output$ini, collapse = " "), "\nHAVE BEEN REPLACED BY\n", paste(tempo.output$post, collapse = " "))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        if( ! (is.null(add) | is.null(tempo.output$ini))){
-            if(grepl(x = add, pattern = paste(tempo.output$ini, collapse = "|"))){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF COLUMN NAMES OF data1 IN THE add ARGUMENT STRING, THAT CORRESPOND TO RESERVED STRINGS FOR ", function.name, "\nCOLUMN NAMES HAVE TO BE CHANGED\nTHE PROBLEMATIC COLUMN NAMES ARE SOME OF THESE NAMES:\n", paste(tempo.output$ini, collapse = " "), "\nIN THE DATA FRAME OF data1 AND IN THE STRING OF add ARGUMENT, TRY TO REPLACE NAMES BY:\n", paste(tempo.output$post, collapse = " "), "\n\nFOR INFORMATION, THE RESERVED WORDS ARE:\n", paste(reserved.words, collapse = "\n"))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-        }
-    }
-    if( ! (is.null(add))){
-        if(any(sapply(X = arg.names, FUN = grepl, x = add), na.rm = TRUE)){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NAMES OF ", function.name, " ARGUMENTS DETECTED IN THE add STRING:\n", paste(arg.names[sapply(X = arg.names, FUN = grepl, x = add)], collapse = "\n"), "\nRISK OF WRONG OBJECT USAGE INSIDE ", function.name)
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end reserved word checking
-    # verif of add
-    if( ! is.null(add)){
-        if( ! grepl(pattern = "^\\s*\\+", add)){ # check that the add string start by +
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nadd ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if( ! grepl(pattern = "(ggplot2|lemon)\\s*::", add)){ #
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nFOR EASIER FUNCTION DETECTION, add ARGUMENT MUST CONTAIN \"ggplot2::\" OR \"lemon::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if( ! grepl(pattern = ")\\s*$", add)){ # check that the add string finished by )
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nadd ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end verif of add
-    # management of add containing facet
-    facet.categ <- NULL
-    if( ! is.null(add)){
-        facet.check <- TRUE
-        tempo <- unlist(strsplit(x = add, split = "\\s*\\+\\s*(ggplot2|lemon)\\s*::\\s*")) #
-        tempo <- sub(x = tempo, pattern = "^facet_wrap", replacement = "ggplot2::facet_wrap")
-        tempo <- sub(x = tempo, pattern = "^facet_grid", replacement = "ggplot2::facet_grid")
-        tempo <- sub(x = tempo, pattern = "^facet_rep", replacement = "lemon::facet_rep")
-        if(any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap"), na.rm = TRUE)){
-            tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")])))
-            facet.categ <- names(tempo1$params$facets)
-            tempo.text <- "facet_wrap OR facet_rep_wrap"
-            facet.check <- FALSE
-        }else if(grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")){
-            tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")])))
-            facet.categ <- c(names(tempo1$params$rows), names(tempo1$params$cols))
-            tempo.text <- "facet_grid OR facet_rep_grid"
-            facet.check <- FALSE
-        }
-        if(facet.check == FALSE & ! all(facet.categ %in% names(data1))){ # WARNING: all(facet.categ %in% names(data1)) is TRUE when facet.categ is NULL # all() without na.rm -> ok because facet.categ cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF \"", tempo.text, "\" STRING IN THE add ARGUMENT BUT PROBLEM OF VARIABLE DETECTION (COLUMN NAMES OF data1)\nTHE DETECTED VARIABLES ARE:\n", paste(facet.categ, collapse = " "), "\nTHE data1 COLUMN NAMES ARE:\n", paste(names(data1), collapse = " "), "\nPLEASE REWRITE THE add STRING AND RERUN")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end management of add containing facet
-    # conversion of categ columns in data1 into factors
-    for(i1 in 1:length(categ)){
-        tempo1 <- fun_check(data = data1[, categ[i1]], data.name = paste0("categ NUMBER ", i1, " OF data1"), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-        tempo2 <- fun_check(data = data1[, categ[i1]], data.name = paste0("categ NUMBER ", i1, " OF data1"), class = "factor", na.contain = TRUE, fun.name = function.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\n", paste0("categ NUMBER ", i1, " OF data1"), " MUST BE A FACTOR OR CHARACTER VECTOR")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(tempo1$problem == FALSE){ # character vector
-            if(box.alpha != 0){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN categ NUMBER ", i1, " IN data1, THE CHARACTER COLUMN HAS BEEN CONVERTED TO FACTOR, WITH LEVELS ACCORDING TO THE ALPHABETICAL ORDER")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        data1[, categ[i1]] <- factor(data1[, categ[i1]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-    }
-    # OK: all the categ columns of data1 are factors from here
-    # end conversion of categ columns in data1 into factors
-    
-    
-    
-    # management of log scale and Inf removal
-    if(any(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf  # normally no NA with is.finite0() and is.na()
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN THE ", y, " COLUMN OF THE data1 ARGUMENT AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    data1.ini <- data1 # strictly identical to data1 except that in data1 y is log converted if and only if y.log != "no"
-    if(y.log != "no"){
-        tempo1 <- ! is.finite(data1[, y]) # where are initial NA and Inf
-        data1[, y] <- suppressWarnings(get(y.log)(data1[, y]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-        if(any( ! (tempo1 | is.finite(data1[, y])))){ # normally no NA with is.finite
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN THE ", y, " COLUMN OF THE data1 ARGUMENT AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # Inf removal
-    if(any(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf # normally no NA with is.finite
-        removed.row.nb <- which(( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])))
-        removed.rows <- data1.ini[removed.row.nb, ] # here data1.ini used to have the y = O rows that will be removed because of Inf creation after log transformation
-        data1 <- data1[-removed.row.nb, ] #
-        data1.ini <- data1.ini[-removed.row.nb, ] #
-    }else{
-        removed.row.nb <- NULL
-        removed.rows <- data.frame(stringsAsFactors = FALSE)
-    }
-    # From here, data1 and data.ini have no more Inf
-    # end Inf removal
-    if(y.log != "no" & ! is.null(y.lim)){
-        if(any(y.lim <= 0)){ # any() without na.rm -> ok because y.lim cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else if(any( ! is.finite(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}))){ # normally no NA with is.finite
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT RETURNS INF/NA WITH THE y.log ARGUMENT SET TO ", y.log, "\nAS SCALE COMPUTATION IS ", ifelse(y.log == "log10", "log10", "log2"), ":\n", paste(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(y.log != "no" & y.include.zero == TRUE){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") y.log ARGUMENT SET TO ", y.log, " AND y.include.zero ARGUMENT SET TO TRUE -> y.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        y.include.zero <- FALSE
-    }
-    if(y.log != "no" & vertical == FALSE){
-        vertical <- TRUE
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") BECAUSE OF A BUG IN ggplot2, CANNOT FLIP BOXES HORIZONTALLY WITH A Y.LOG SCALE -> vertical ARGUMENT RESET TO TRUE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    # end management of log scale and Inf removal
-    # na detection and removal (done now to be sure of the correct length of categ)
-    column.check <- unique(c(y, categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){dot.categ}, if( ! is.null(facet.categ)){facet.categ})) # dot.categ because can be a 3rd column of data1, categ.color and dot.color will be tested later
-    if(any(is.na(data1[, column.check]))){ # data1 used here instead of data1.ini in case of new NaN created by log conversion (neg values) # normally no NA with is.na
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS OF data1 AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        for(i2 in 1:length(column.check)){
-            if(any(is.na(data1[, column.check[i2]]))){ # normally no NA with is.na
-                tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i2], " OF data1")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n", tempo.warn)))
-            }
-        }
-        tempo <- unique(unlist(lapply(lapply(c(data1[column.check]), FUN = is.na), FUN = which)))
-        removed.row.nb <- c(removed.row.nb, tempo) # removed.row.nb created to remove Inf
-        removed.rows <- rbind(removed.rows, data1.ini[tempo, ], stringsAsFactors = FALSE) # here data1.ini used to have the non NA rows that will be removed because of NAN creation after log transformation (neg values for instance)
-        column.check <- column.check[ ! column.check == y] # remove y to keep quali columns
-        if(length(tempo) != 0){
-            data1 <- data1[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
-            data1.ini <- data1.ini[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers than the former
-            for(i3 in 1:length(column.check)){
-                if(any( ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]]), na.rm = TRUE)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i3], " OF data1, THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA/Inf REMOVAL (IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[, column.check[i3]])[ ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]])], collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-        }
-        count.categ <- 0
-        for(i2 in 1:length(column.check)){
-            if(column.check[i2] %in% categ){
-                count.categ <- count.categ + 1
-            }
-            if(column.check[i2] == categ[count.categ]){
-                categ.class.order[count.categ] <- list(levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])]) # remove the absent color in the character vector
-                data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(categ.class.order[[count.categ]]))
-            }
-            if( ! is.null(dot.color) & ! is.null(dot.categ)){ # reminder : dot.categ cannot be a column name of categ anymore (because in that case dot.categ name is changed into "..._DOT"
-                if(column.check[i2] == dot.categ){
-                    dot.categ.class.order <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
-                    data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(dot.categ.class.order))
-                }
-            }
-            if(column.check[i2] %in% facet.categ){ # works if facet.categ == NULL this method should keep the order of levels when removing some levels
-                tempo.levels <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(as.character(data1[, column.check[i2]]))]
-                data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = tempo.levels)
-            }
-        }
-    }
-    # end na detection and removal (done now to be sure of the correct length of categ)
-    # From here, data1 and data.ini have no more NA or NaN in y, categ, dot.categ (if dot.color != NULL) and facet.categ
-    
-    
-    
-    if( ! is.null(categ.class.order)){
-        if(length(categ.class.order) != length(categ)){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.class.order ARGUMENT MUST BE A LIST OF LENGTH EQUAL TO LENGTH OF categ\nHERE IT IS LENGTH: ", length(categ.class.order), " VERSUS ", length(categ))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            for(i3 in 1:length(categ.class.order)){
-                if(is.null(categ.class.order[[i3]])){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE categ.class.order COMPARTMENT ", i3, " IS NULL. ALPHABETICAL ORDER WILL BE APPLIED")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    data1[, categ[i3]] <- factor(as.character(data1[, categ[i3]])) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                    categ.class.order[[i3]] <- levels(data1[, categ[i3]]) # character vector that will be used later
-                }else{
-                    tempo <- fun_check(data = categ.class.order[[i3]], data.name = paste0("COMPARTMENT ", i3 , " OF categ.class.order ARGUMENT"), class = "vector", mode = "character", length = length(levels(data1[, categ[i3]])), fun.name = function.name) # length(data1[, categ[i1]) -> if data1[, categ[i1] was initially character vector, then conversion as factor after the NA removal, thus class number ok. If data1[, categ[i1] was initially factor, no modification after the NA removal, thus class number ok
-                    if(tempo$problem == TRUE){
-                        stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-                    }
-                }
-                if(any(duplicated(categ.class.order[[i3]]), na.rm = TRUE)){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i3, " OF categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(categ.class.order[[i3]], collapse = " "))
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else if( ! (all(categ.class.order[[i3]] %in% unique(data1[, categ[i3]]), na.rm = TRUE) & all(unique(data1[, categ[i3]]) %in% categ.class.order[[i3]], na.rm = TRUE))){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i3, " OF categ.class.order ARGUMENT MUST BE CLASSES OF ELEMENT ", i3, " OF categ ARGUMENT\nHERE IT IS:\n", paste(categ.class.order[[i3]], collapse = " "), "\nFOR COMPARTMENT ", i3, " OF categ.class.order AND IT IS:\n", paste(unique(data1[, categ[i3]]), collapse = " "), "\nFOR COLUMN ", categ[i3], " OF data1")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else{
-                    data1[, categ[i3]] <- factor(data1[, categ[i3]], levels = categ.class.order[[i3]]) # reorder the factor
-                    
-                }
-                names(categ.class.order)[i3] <- categ[i3]
-            }
-        }
-    }else{
-        categ.class.order <- vector("list", length = length(categ))
-        tempo.categ.class.order <- NULL
-        for(i2 in 1:length(categ.class.order)){
-            categ.class.order[[i2]] <- levels(data1[, categ[i2]])
-            names(categ.class.order)[i2] <- categ[i2]
-            tempo.categ.class.order <- c(tempo.categ.class.order, ifelse(i2 != 1, "\n", ""), categ.class.order[[i2]])
-        }
-        if(box.alpha != 0){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR BOX ORDERING:\n", paste(tempo.categ.class.order, collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # categ.class.order not NULL anymore (list)
-    if(is.null(box.legend.name) & box.alpha != 0){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE box.legend.name SETTING IS NULL. NAMES OF categ WILL BE USED: ", paste(categ, collapse = " "))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        box.legend.name <- categ[length(categ)] # if only categ1, then legend name of categ1, if length(categ) == 2L, then legend name of categ2
-    }
-    # box.legend.name not NULL anymore (character string)
-    # management of categ.color
-    if( ! is.null(categ.color)){
-        # check the nature of color
-        # integer colors into gg_palette
-        tempo.check.color <- fun_check(data = categ.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem
-        if(tempo.check.color == FALSE){
-            # convert integers into colors
-            categ.color <- fun_gg_palette(max(categ.color, na.rm = TRUE))[categ.color]
-        }
-        # end integer colors into gg_palette
-        if( ! (all(categ.color %in% colors() | grepl(pattern = "^#", categ.color)))){ # check that all strings of low.color start by #, # all() without na.rm -> ok because categ.color cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors(): ", paste(unique(categ.color), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(is.na(categ.color)) & box.alpha != 0){ # normally no NA with is.na
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT CONTAINS NA")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        # end check the nature of color
-        # check the length of color
-        categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
-        if(length(data1[, categ[categ.len]]) == length(levels(data1[, categ[categ.len]])) & length(categ.color) == length(data1[, categ[categ.len]])){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE NUMBER OF CLASSES OF THE COLUMN ", categ[categ.len], " THE NUMBER OF ROWS OF THIS COLUMN AND THE NUMBER OF COLORS OF THE categ.color ARGUMENT ARE ALL EQUAL. BOX COLORS WILL BE ATTRIBUTED ACCORDING THE LEVELS OF ", categ[categ.len], ", NOT ACCORDING TO THE ROWS OF ", categ[categ.len])
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        if(length(categ.color) == length(levels(data1[, categ[categ.len]]))){ # here length(categ.color) is equal to the different number of categ
-            # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-            data1 <- data.frame(data1, categ.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)  # no need stringsAsFactors here for stat.nolog as factors remain factors
-            data1$categ.color <- factor(data1$categ.color, labels = categ.color) # replace the characters of data1[, categ[categ.len]] put in the categ.color column by the categ.color (can be write like this because categ.color is length of levels of data1[, categ[categ.len]])
-            if(box.alpha != 0){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN ", categ[categ.len], " OF categ ARGUMENT, THE FOLLOWING COLORS:\n", paste(categ.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "))
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }else if(length(categ.color) == length(data1[, categ[categ.len]])){# here length(categ.color) is equal to nrow(data1) -> Modif to have length(categ.color) equal to the different number of categ (length(categ.color) == length(levels(data1[, categ[categ.len]])))
-            data1 <- data.frame(data1, categ.color = categ.color, stringsAsFactors = TRUE)
-            tempo.check <- unique(data1[ , c(categ[categ.len], "categ.color")])
-            if( ! (nrow(tempo.check) == length(unique(categ.color)) & nrow(tempo.check) == length(unique(data1[ , categ[categ.len]])))){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT HAS THE LENGTH OF data1 ROW NUMBER\nBUT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF categ ", categ[categ.len], ":\n", paste(unique(mapply(FUN = "paste", data1[ ,categ[categ.len]], data1[ ,"categ.color"])), collapse = "\n"))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-                categ.color <- unique(data1$categ.color[order(data1[, categ[categ.len]])]) # Modif to have length(categ.color) equal to the different number of categ (length(categ.color) == length(levels(data1[, categ[categ.len]])))
-                if(box.alpha != 0){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT HAS THE LENGTH OF data1 ROW NUMBER\nCOLORS HAVE BEEN RESPECTIVELY ASSOCIATED TO EACH CLASS OF categ ", categ[categ.len], " AS:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\n", paste(categ.color, collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-        }else if(length(categ.color) == 1L){
-            # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-            data1 <- data.frame(data1, categ.color = categ.color, stringsAsFactors = TRUE)
-            categ.color <- rep(categ.color, length(levels(data1[, categ[categ.len]])))
-            if(box.alpha != 0){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") categ.color ARGUMENT HAS LENGTH 1, MEANING THAT ALL THE DIFFERENT CLASSES OF ", categ[categ.len], "\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(categ.color, collapse = " "))
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ncateg.color ARGUMENT MUST BE (1) LENGTH 1, OR (2) THE LENGTH OF data1 NROWS AFTER NA/Inf REMOVAL, OR (3) THE LENGTH OF THE CLASSES IN THE categ ", categ[categ.len], " COLUMN. HERE IT IS COLOR LENGTH ", length(categ.color), " VERSUS CATEG LENGTH ", length(data1[, categ[categ.len]]), " AND CATEG CLASS LENGTH ", length(unique(data1[, categ[categ.len]])), "\nPRESENCE OF NA/Inf COULD BE THE PROBLEM")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else{
-        categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
-        # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-        categ.color <- fun_gg_palette(length(levels(data1[, categ[categ.len]])))
-        data1 <- data.frame(data1, categ.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)
-        data1$categ.color <- factor(data1$categ.color, labels = categ.color)  # replace the characters of data1[, categ[categ.len]] put in the categ.color column by the categ.color (can be write like this because categ.color is length of levels of data1[, categ[categ.len]])
-        if(box.alpha != 0){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NULL categ.color ARGUMENT -> COLORS RESPECTIVELY ATTRIBUTED TO EACH CLASS OF ", categ[categ.len], " IN data1:\n", paste(categ.color, collapse = " "), "\n", paste(levels(data1[, categ[categ.len]]), collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # categ.color not NULL anymore
-    categ.color <- as.character(categ.color)
-    # categ.color is a character string representing the diff classes
-    data1$categ.color <- factor(data1$categ.color, levels = unique(categ.color)) # ok because if categ.color is a character string, the order make class 1, class 2, etc. unique() because no duplicates allowed
-    # data1$categ.color is a factor with order of levels -> categ.color
-    # end management of categ.color
-    # management of dot.color
-    if( ! is.null(dot.color)){
-        # optional legend of dot colors
-        if( ! is.null(dot.categ)){
-            ini.dot.categ <- dot.categ
-            if( ! dot.categ %in% names(data1)){ # no need to use all() because length(dot.categ) = 1
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT MUST BE A COLUMN NAME OF data1. HERE IT IS:\n", dot.categ)
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else if(dot.categ %in% categ){ # no need to use all() because length(dot.categ) = 1. Do not use dot.categ %in% categ[length(categ)] -> error
-                # management of dot legend if dot.categ %in% categ (because legends with the same name are joined in ggplot2) 
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") THE COLUMN NAME OF data1 INDICATED IN THE dot.categ ARGUMENT (", dot.categ, ") HAS BEEN REPLACED BY ", paste0(dot.categ, "_DOT"), " TO AVOID MERGED LEGEND BY GGPLOT2")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                data1 <- data.frame(data1, dot.categ = data1[, dot.categ], stringsAsFactors = TRUE) # dot.categ is not a column name of data1 (checked above with reserved words)
-                dot.categ <- paste0(dot.categ, "_DOT")
-                names(data1)[names(data1) == "dot.categ"] <- dot.categ # paste0(dot.categ, "_DOT") is not a column name of data1 (checked above with reserved words)
-                # tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ ARGUMENT CANNOT BE A COLUMN NAME OF data1 ALREADY SPECIFIED IN THE categ ARGUMENT:\n", dot.categ, "\nINDEED, dot.categ ARGUMENT IS MADE TO HAVE MULTIPLE DOT COLORS NOT RELATED TO THE BOXPLOT CATEGORIES")
-                # stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            tempo1 <- fun_check(data = data1[, dot.categ], data.name = paste0(dot.categ, " COLUMN OF data1"), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-            tempo2 <- fun_check(data = data1[, dot.categ], data.name = paste0(dot.categ, " COLUMN OF data1"), class = "factor", na.contain = TRUE, fun.name = function.name)
-            if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ COLUMN MUST BE A FACTOR OR CHARACTER VECTOR") #
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            data1[, dot.categ] <- factor(data1[, dot.categ]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-            # dot.categ column of data1 is factor from here
-            if( ! is.null(dot.categ.class.order)){
-                if(any(duplicated(dot.categ.class.order), na.rm = TRUE)){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(dot.categ.class.order, collapse = " "))
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else if( ! (all(dot.categ.class.order %in% levels(data1[, dot.categ])) & all(levels(data1[, dot.categ]) %in% dot.categ.class.order, na.rm = TRUE))){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.categ.class.order ARGUMENT MUST BE CLASSES OF dot.categ ARGUMENT\nHERE IT IS:\n", paste(dot.categ.class.order, collapse = " "), "\nFOR dot.categ.class.order AND IT IS:\n", paste(levels(data1[, dot.categ]), collapse = " "), "\nFOR dot.categ COLUMN (", ini.dot.categ, ") OF data1")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else{
-                    data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
-                }
-            }else{
-                if(all(dot.color == "same") & length(dot.color)== 1L){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
-                    dot.categ.class.order <- unlist(categ.class.order[length(categ)])
-                    data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order SETTING IS NULL AND dot.color IS \"same\". ORDER OF categ.class.order WILL BE APPLIED FOR LEGEND DISPLAY: ", paste(dot.categ.class.order, collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }else{
-                    dot.categ.class.order <- sort(levels(data1[, dot.categ]))
-                    data1[, dot.categ] <- factor(data1[, dot.categ], levels = dot.categ.class.order) # reorder the factor
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR LEGEND DISPLAY: ", paste(dot.categ.class.order, collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            # dot.categ.class.order not NULL anymore (character string) if dot.categ is not NULL
-            if(all(dot.color == "same") & length(dot.color)== 1L){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
-                if( ! identical(ini.dot.categ, categ[length(categ)])){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN dot.color ARGUMENT IS \"same\", THE COLUMN NAME IN dot.categ ARGUMENT MUST BE IDENTICAL TO THE LAST COLUMN NAME IN categ ARGUMENT. HERE IT IS:\ndot.categ: ", paste(ini.dot.categ, collapse = " "), "\ncateg: ", paste(categ, collapse = " "))
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }else if( ! fun_comp_1d(unlist(categ.class.order[length(categ)]), dot.categ.class.order)$identical.content){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN dot.color ARGUMENT IS \"same\",\nLAST COMPARTMENT OF categ.class.order ARGUMENT AND dot.categ.class.order ARGUMENT CANNOT BE DIFFERENT:\nLAST COMPARTMENT OF categ.class.order: ", paste(unlist(categ.class.order[length(categ)]), collapse = " "), "\ndot.categ.class.order: ", paste(dot.categ.class.order, collapse = " "))
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }
-            }
-            for(i3 in 1:length(categ)){
-                if(identical(categ[i3], ini.dot.categ) & ! identical(unlist(categ.class.order[i3]), dot.categ.class.order) & identical(sort(unlist(categ.class.order[i3])), sort(dot.categ.class.order))){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE dot.categ ARGUMENT SETTING IS PRESENT IN THE categ ARGUMENT SETTING, BUT ORDER OF THE CLASSES IS NOT THE SAME:\ncateg.class.order: ", paste(unlist(categ.class.order[i3]), collapse = " "), "\ndot.categ.class.order: ", paste(dot.categ.class.order, collapse = " "), "\nNOTE THAT ORDER OF categ.class.order IS THE ONE USED FOR THE AXIS REPRESENTATION")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            if(is.null(dot.legend.name)){
-                dot.legend.name <- if(ini.dot.categ %in% categ[length(categ)]){dot.categ}else{ini.dot.categ} #
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") THE dot.legend.name SETTING IS NULL -> ", dot.legend.name, " WILL BE USED AS LEGEND TITLE OF DOTS")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # dot.legend.name not NULL anymore (character string)
-        }else{
-            if( ! is.null(dot.categ.class.order)){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") THE dot.categ.class.order ARGUMENT IS NOT NULL, BUT IS THE dot.categ ARGUMENT\n-> dot.categ.class.order NOT CONSIDERED AS NO LEGEND WILL BE DRAWN")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # But dot.categ.class.order will be converted to NULL below (not now)
-        }
-        # end optional legend of dot colors
-        # check the nature of color
-        # integer colors into gg_palette
-        tempo.check.color <- fun_check(data = dot.color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem
-        if(tempo.check.color == FALSE){
-            # convert integers into colors
-            dot.color <- fun_gg_palette(max(dot.color, na.rm = TRUE))[dot.color]
-        }
-        # end integer colors into gg_palette
-        if(all(dot.color == "same") & length(dot.color)== 1L){# all() without na.rm -> ok because dot.color cannot be NA (tested above)
-            dot.color <- categ.color # same color of the dots as the corresponding box color
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT HAS BEEN SET TO \"same\"\nTHUS, DOTS WILL HAVE THE SAME COLORS AS THE CORRESPONDING BOXPLOT")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }else if( ! (all(dot.color %in% colors() | grepl(pattern = "^#", dot.color)))){ # check that all strings of low.color start by #, # all() without na.rm -> ok because dot.color cannot be NA (tested above)
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE (1) A HEXADECIMAL COLOR VECTOR STARTING BY #, OR (2) COLOR NAMES GIVEN BY colors(), OR (3) INTEGERS, OR THE STRING \"same\"\nHERE IT IS: ", paste(unique(dot.color), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        if(any(is.na(dot.color))){ # normally no NA with is.finite
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT CONTAINS NA")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        # end check the nature of color
-        # check the length of color
-        if( ! is.null(dot.categ)){
-            # optional legend of dot colors
-            if(length(data1[, dot.categ]) == length(levels(data1[, dot.categ])) & length(dot.color) == length(data1[, dot.categ])){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") THE NUMBER OF CLASSES OF THE COLUMN ", dot.categ, " THE NUMBER OF ROWS OF THIS COLUMN AND THE NUMBER OF COLORS OF THE dot.color ARGUMENT ARE ALL EQUAL. DOT COLORS WILL BE ATTRIBUTED ACCORDING THE LEVELS OF ", dot.categ, ", NOT ACCORDING TO THE ROWS OF ", dot.categ)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            if(length(dot.color) > 1 & ! (length(dot.color) == length(unique(data1[, dot.categ])) | length(dot.color) == length(data1[, dot.categ]))){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nWHEN LENGTH OF THE dot.color ARGUMENT IS MORE THAN 1, IT MUST BE EQUAL TO THE NUMBER OF 1) ROWS OR 2) LEVELS OF dot.categ COLUMN (", dot.categ, "):\ndot.color: ", paste(dot.color, collapse = " "), "\ndot.categ LEVELS: ", paste(levels(data1[, dot.categ]), collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else if(length(dot.color) > 1 & length(dot.color) == length(unique(data1[, dot.categ]))){
-                data1 <- data.frame(data1, dot.color = data1[, dot.categ], stringsAsFactors = TRUE)
-                data1$dot.color <- factor(data1$dot.color, labels = dot.color) # do not use labels = unique(dot.color). Otherwise, we can have green1 green2 when dot.color is c("green", "green")
-            }else if(length(dot.color) > 1 & length(dot.color) == length(data1[, dot.categ])){
-                data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
-            }else if(length(dot.color)== 1L){ # to deal with single color. Warning: & length(dot.categ.class.order) > 1 removed because otherwise, the data1 is not with dot.color column when length(dot.categ.class.order) == 1
-                data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
-            }
-            dot.color <- as.character(unique(data1$dot.color[order(data1[, dot.categ])])) # reorder the dot.color character vector
-            if(length(dot.color)== 1L & length(dot.categ.class.order) > 1){ # to deal with single color
-                dot.color <- rep(dot.color, length(dot.categ.class.order))
-            }
-            tempo.check <- unique(data1[ , c(dot.categ, "dot.color")])
-            if(length(unique(data1[ , "dot.color"])) > 1 & ( ! (nrow(tempo.check) == length(unique(data1[ , "dot.color"])) & nrow(tempo.check) == length(unique(data1[ , dot.categ]))))){ # length(unique(data1[ , "dot.color"])) > 1 because if only one color, can be attributed to each class of dot.categ
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF dot.categ (", dot.categ, ") COLUMN:\n", paste(unique(mapply(FUN = "paste", data1[ , dot.categ], data1[ ,"dot.color"])), collapse = "\n"))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN dot.categ ARGUMENT (", ini.dot.categ, "), THE FOLLOWING COLORS OF DOTS:\n", paste(dot.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(data1[, dot.categ]), collapse = " "))
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # dot.color is a character string representing the diff classes of dot.categ
-            # data1$dot.color is a factor with order of levels -> dot.categ
-            # end optional legend of dot colors
-        }else{
-            categ.len <- length(categ) # if only categ1, then colors for classes of categ1, if length(categ) == 2L, then colors for classes of categ2
-            if(length(dot.color) == length(levels(data1[, categ[categ.len]]))){ # here length(dot.color) is equal to the different number of categ
-                # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-                data1 <- data.frame(data1, dot.color = data1[, categ[categ.len]], stringsAsFactors = TRUE)
-                data1$dot.color <- factor(data1$dot.color, labels = dot.color)
-                if(box.alpha != 0){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN ", categ[categ.len], " OF categ ARGUMENT, THE FOLLOWING COLORS:\n", paste(dot.color, collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }else if(length(dot.color) == length(data1[, categ[categ.len]])){# here length(dot.color) is equal to nrow(data1) -> Modif to have length(dot.color) equal to the different number of categ (length(dot.color) == length(levels(data1[, categ[categ.len]])))
-                data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
-            }else if(length(dot.color)== 1L & ! all(dot.color == "same")){ # all() without na.rm -> ok because dot.color cannot be NA (tested above)
-                # data1[, categ[categ.len]] <- factor(data1[, categ[categ.len]]) # not required because sure that is is a factor
-                data1 <- data.frame(data1, dot.color = dot.color, stringsAsFactors = TRUE)
-                dot.color <- rep(dot.color, length(levels(data1[, categ[categ.len]])))
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") dot.color ARGUMENT HAS LENGTH 1, MEANING THAT ALL THE DIFFERENT CLASSES OF ", categ[categ.len], "\n", paste(levels(factor(data1[, categ[categ.len]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(dot.color, collapse = " "))
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }else{
-                tempo.cat <- paste0("ERROR IN ", function.name, "\ndot.color ARGUMENT MUST BE (1) LENGTH 1, OR (2) THE LENGTH OF data1 NROWS AFTER NA/Inf REMOVAL, OR (3) THE LENGTH OF THE CLASSES IN THE categ ", categ[categ.len], " COLUMN. HERE IT IS COLOR LENGTH ", length(dot.color), " VERSUS CATEG LENGTH ", length(data1[, categ[categ.len]]), " AND CATEG CLASS LENGTH ", length(unique(data1[, categ[categ.len]])), "\nPRESENCE OF NA/Inf COULD BE THE PROBLEM")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            # end check the length of color
-            dot.color <- as.character(dot.color)
-            # dot.color is a character string representing the diff classes
-            data1$dot.color <- factor(data1$dot.color, levels = unique(dot.color)) # ok because if dot.color is a character string, the order make class 1, class 2, etc. If dot.color is a column of data1, then levels will be created, without incidence, except if dot.categ specified (see below). unique() because no duplicates allowed
-            # data1$dot.color is a factor with order of levels -> dot.color
-        }
-        # end optional legend of dot colors
-    }else if(is.null(dot.color) & ! (is.null(dot.categ) & is.null(dot.categ.class.order) & is.null(dot.legend.name))){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") dot.categ OR dot.categ.class.order OR dot.legend.name ARGUMENT HAS BEEN SPECIFIED BUT dot.color ARGUMENT IS NULL (NO DOT PLOTTED)")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    # dot.color either NULL (no dot plotted) or character string (potentially representing the diff classes of dot.categ)
-    # data1$dot.color is either NA or a factor (with order of levels -> depending on dot.categ or categ[length(categ)], or other
-    if(is.null(dot.categ)){
-        dot.categ.class.order <- NULL # because not used anyway
-    }
-    # dot.categ.class.order either NULL if dot.categ is NULL (no legend displayed) or character string (potentially representing the diff classes of dot.categ)
-    # end management of dot.color
-    if(is.null(dot.color) & box.fill == FALSE & dot.alpha <= 0.025){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") THE FOLLOWING ARGUMENTS WERE SET AS:\ndot.color = NULL (NOT ALL DOTS BUT ONLY POTENTIAL OUTLIER DOTS DISPLAYED)\nbox.fill = FALSE (NO FILLING COLOR FOR BOTH BOXES AND POTENTIAL OUTLIER DOTS)\ndot.alpha = ", fun_round(dot.alpha, 4), "\n-> POTENTIAL OUTLIER DOTS MIGHT NOT BE VISIBLE BECAUSE ALMOST TRANSPARENT")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    if(is.null(dot.color) & box.fill == FALSE & dot.border.size == 0){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE FOLLOWING ARGUMENTS WERE SET AS:\ndot.color = NULL (NOT ALL DOTS BUT ONLY POTENTIAL OUTLIER DOTS DISPLAYED)\nbox.fill = FALSE (NO FILLING COLOR FOR BOTH BOXES AND POTENTIAL OUTLIER DOTS)\ndot.border.size = 0 (NO BORDER FOR POTENTIAL OUTLIER DOTS)\n-> THESE SETTINGS ARE NOT ALLOWED BECAUSE THE POTENTIAL OUTLIER DOTS WILL NOT BE VISIBLE")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # integer dot.border.color into gg_palette
-    if( ! is.null(dot.border.color)){
-        tempo <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
-        if(tempo$problem == FALSE){ # convert integers into colors
-            dot.border.color <- fun_gg_palette(max(dot.border.color, na.rm = TRUE))[dot.border.color]
-        }
-    }
-    # end integer dot.border.color into gg_palette
-    # na detection and removal (done now to be sure of the correct length of categ)
-    column.check <- c("categ.color", if( ! is.null(dot.color)){"dot.color"}) # 
-    if(any(is.na(data1[, column.check]))){ # data1 used here instead of data1.ini in case of new NaN created by log conversion (neg values) # normally no NA with is.na
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS ", paste(column.check, collapse = " "), " OF data1 AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        for(i2 in 1:length(column.check)){
-            if(any(is.na(data1[, column.check[i2]]))){ # normally no NA with is.na
-                tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i2], " OF data1")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n", tempo.warn)))
-            }
-        }
-        tempo <- unique(unlist(lapply(lapply(c(data1[column.check]), FUN = is.na), FUN = which)))
-        removed.row.nb <- c(removed.row.nb, tempo)
-        removed.rows <- rbind(removed.rows, data1[tempo, ], stringsAsFactors = FALSE) # here data1 used because categorical columns tested
-        if(length(tempo) != 0){
-            data1 <- data1[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
-            data1.ini <- data1.ini[-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
-            for(i3 in 1:length(column.check)){
-                if(any( ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]]), na.rm = TRUE)){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i3], " OF data1, THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA/Inf REMOVAL (IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[, column.check[i3]])[ ! unique(removed.rows[, column.check[i3]]) %in% unique(data1[, column.check[i3]])], collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-        }
-        for(i2 in 1:length(column.check)){
-            if(column.check[i2] == "categ.color"){
-                categ.color <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
-                if(length(categ.color)== 1L & length(unlist(categ.class.order[length(categ)])) > 1){ # to deal with single color
-                    categ.color <- rep(categ.color, length(unlist(categ.class.order[length(categ)])))
-                }
-                data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(categ.color))
-            }
-            if(column.check[i2] == "dot.color"){
-                dot.color <- levels(data1[, column.check[i2]])[levels(data1[, column.check[i2]]) %in% unique(data1[, column.check[i2]])] # remove the absent color in the character vector
-                if(length(dot.color)== 1L & length(dot.categ.class.order) > 1){ # to deal with single color. If dot.categ.class.order == NULL (which is systematically the case if dot.categ == NULL), no rep(dot.color, length(dot.categ.class.order)
-                    dot.color <- rep(dot.color, length(dot.categ.class.order))
-                }
-                data1[, column.check[i2]] <- factor(as.character(data1[, column.check[i2]]), levels = unique(dot.color))
-            }
-        }
-    }
-    # end na detection and removal (done now to be sure of the correct length of categ)
-    # From here, data1 and data.ini have no more NA or NaN
-    # end other checkings
-    # reserved word checking
-    #already done above
-    # end reserved word checking
-    # end second round of checking and data preparation
-    
-    
-    # package checking
-    fun_pack(req.package = c(
-        "ggplot2", 
-        "gridExtra", 
-        "lemon", 
-        "scales"
-    ), lib.path = lib.path)
-    # end package checking
-    
-    
-    
-    
-    
-    # main code
-    # y coordinates recovery (create ini.box.coord, dot.coord and modify data1)
-    if(length(categ)== 1L){
-        # width commputations
-        box.width2 <- box.width
-        box.space <- 0 # to inactivate the shrink that add space between grouped boxes, because no grouped boxes here
-        # end width commputations
-        # data1 check categ order for dots coordinates recovery
-        data1 <- data.frame(data1, categ.check = data1[, categ[1]], stringsAsFactors = TRUE)
-        data1$categ.check <- as.integer(data1$categ.check) # to check that data1[, categ[1]] and dot.coord$group are similar, during merging
-        # end data1 check categ order for dots coordinates recovery
-        # per box dots coordinates recovery
-        tempo.gg.name <- "gg.indiv.plot."
-        tempo.gg.count <- 0
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[1]), stroke = dot.border.size, size = dot.size, alpha = dot.alpha, shape = 21))
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(is.null(categ.color)){rep(NA, length(unique(data1[, categ[1]])))}else if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[1]])))}else{categ.color})) # categ.color used for dot colors because at that stage, we do not care about colors
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[1]), coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf})) # fill because this is what is used with geom_box # to easily have the equivalent of the grouped boxes
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[1]])))}else{categ.color}))
-        # end per box dots coordinates recovery
-    }else if(length(categ) == 2L){
-        # width commputations
-        box.width2 <- box.width / length(unique(data1[, categ[length(categ)]])) # real width of each box in x-axis unit, among the set of grouped box. Not relevant if no grouped boxes length(categ)== 1L
-        # end width commputations
-        # data1 check categ order for dots coordinates recovery
-        tempo.factor <- paste0(data1[order(data1[, categ[2]], data1[, categ[1]]), categ[2]], "_", data1[order(data1[, categ[2]], data1[, categ[1]]), categ[1]])
-        data1 <- data.frame(data1[order(data1[, categ[2]], data1[, categ[1]]), ], categ.check = factor(tempo.factor, levels = unique(tempo.factor)), stringsAsFactors = TRUE)
-        data1$categ.check <- as.integer(data1$categ.check)
-        # end data1 check categ order for dots coordinates recovery
-        # per box dots coordinates recovery
-        tempo.gg.name <- "gg.indiv.plot."
-        tempo.gg.count <- 0
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[2]), stroke = dot.border.size, size = dot.size, alpha = dot.alpha, shape = 21))
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(is.null(categ.color)){rep(NA, length(unique(data1[, categ[2]])))}else if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[2]])))}else{categ.color})) # categ.color used for dot colors because at that stage, we do not care about colors
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[2]), coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf})) # fill because this is what is used with geom_box # to easily have the equivalent of the grouped boxes
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[2]])))}else{categ.color}))
-        # end per box dots coordinates recovery
-    }else{
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 1")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if( ! is.null(stat.pos)){
-        stat.just <- fun_gg_just(
-            angle = stat.angle, 
-            pos = ifelse(
-                vertical == TRUE, 
-                ifelse(stat.pos == "top", "bottom", "top"), # "bottom" because we want justification for text that are below the ref point which is the top of the graph. The opposite for "above"
-                ifelse(stat.pos == "top", "left", "right") # "left" because we want justification for text that are on the left of the ref point which is the right border of the graph. The opposite for "above"
-            ), 
-            kind = "text"
-        )
-    }
-    # has in fact no interest because ggplot2 does not create room for geom_text()
-    tempo.data.max <- data1[which.max(data1[, y]), ]
-    tempo.data.max <- data.frame(tempo.data.max, label = formatC(tempo.data.max[, y], digit = 2, drop0trailing = TRUE, format = "f"), stringsAsFactors = TRUE)
-    # end has in fact no interest because ggplot2 does not create room for geom_text()
-    tempo.graph.info.ini <- ggplot2::ggplot_build(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if( ! is.null(stat.pos)){' + ggplot2::geom_text(data = tempo.data.max, mapping = ggplot2::aes_string(x = 1, y = y, label = "label"), size = stat.size, color = "black", angle = stat.angle, hjust = stat.just$hjust, vjust = stat.just$vjust)'})))) # added here to have room for annotation
-    dot.coord <- tempo.graph.info.ini$data[[1]]
-    dot.coord$x <- as.numeric(dot.coord$x) # because weird class
-    dot.coord$PANEL <- as.numeric(dot.coord$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
-    tempo.mean <- aggregate(x = dot.coord$y, by = list(dot.coord$group, dot.coord$PANEL), FUN = mean, na.rm = TRUE)
-    names(tempo.mean)[names(tempo.mean) == "x"] <- "MEAN"
-    names(tempo.mean)[names(tempo.mean) == "Group.1"] <- "BOX"
-    names(tempo.mean)[names(tempo.mean) == "Group.2"] <- "PANEL"
-    dot.coord <- data.frame(
-        dot.coord[order(dot.coord$group, dot.coord$y), ], # dot.coord$PANEL deals below
-        y.check = as.double(data1[order(data1$categ.check, data1[, y]), y]), 
-        categ.check = data1[order(data1$categ.check, data1[, y]), "categ.check"], 
-        dot.color = if(is.null(dot.color)){NA}else{data1[order(data1$categ.check, data1[, y]), "dot.color"]}, 
-        data1[order(data1$categ.check, data1[, y]), ][categ], # avoid the renaming below
-        stringsAsFactors = TRUE
-    ) # y.check to be sure that the order is the same between the y of data1 and the y of dot.coord
-    # names(dot.coord)[names(dot.coord) == "tempo.categ1"] <- categ[1]
-    if( ! is.null(dot.categ)){
-        dot.coord <- data.frame(dot.coord, data1[order(data1$categ.check, data1[, y]), ][dot.categ], stringsAsFactors = TRUE) # avoid the renaming
-    }
-    if( ! is.null(facet.categ)){
-        dot.coord <- data.frame(dot.coord, data1[order(data1$categ.check, data1[, y]), ][facet.categ], stringsAsFactors = TRUE) # for facet panels
-        tempo.test <- NULL
-        for(i2 in 1:length(facet.categ)){
-            tempo.test <- paste0(tempo.test, ".", formatC(as.numeric(dot.coord[, facet.categ[i2]]), width = nchar(max(as.numeric(dot.coord[, facet.categ[i2]]), na.rm = TRUE)), flag = "0")) # convert factor into numeric with leading zero for proper ranking # merge the formatC() to create a new factor. The convertion to integer should recreate the correct group number. Here as.numeric is used and not as.integer in case of numeric in facet.categ (because comes from add and not checked by fun_check, contrary to categ)
-        }
-        tempo.test <- as.integer(factor(tempo.test))
-        if( ! identical(as.integer(dot.coord$PANEL), tempo.test)){
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nas.integer(dot.coord$PANEL) AND tempo.test MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(dot.tidy == TRUE){
-        if( ! is.null(dot.categ)){
-            dot.coord <- data.frame(dot.coord, tidy_group = data1[order(data1$categ.check, data1[, y]), ][, dot.categ], stringsAsFactors = TRUE) # avoid the renaming
-            # tidy_group_coord is to be able to fuse table when creating the table for dot coordinates
-            if(dot.categ %in% categ){
-                dot.coord <- data.frame(dot.coord, tidy_group_coord = dot.coord$group, stringsAsFactors = TRUE)
-            }else{
-                dot.coord <- data.frame(dot.coord, tidy_group_coord = as.integer(factor(paste0(
-                    formatC(as.integer(dot.coord[, categ[1]]), width = nchar(max(as.integer(dot.coord[, categ[1]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
-                    ".", 
-                    if(length(categ) == 2L){formatC(as.integer(dot.coord[, categ[2]]), width = nchar(max(as.integer(dot.coord[, categ[2]]), na.rm = TRUE)), flag = "0")}, # convert factor into numeric with leading zero for proper ranking
-                    if(length(categ) == 2L){"."}, 
-                    formatC(as.integer(dot.coord[, dot.categ]), width = nchar(max(as.integer(dot.coord[, dot.categ]), na.rm = TRUE)), flag = "0") # convert factor into numeric with leading zero for proper ranking
-                )), stringsAsFactors = TRUE) # merge the 2 or 3 formatC() to create a new factor. The convertion to integer should recreate the correct group number
-                ) # for tidy dot plots
-            }
-        }else{
-            dot.coord <- data.frame(dot.coord, tidy_group = if(length(categ)== 1L){
-                dot.coord[, categ]}else{as.integer(factor(paste0(
-                    formatC(as.integer(dot.coord[, categ[1]]), width = nchar(max(as.integer(dot.coord[, categ[1]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
-                    ".", 
-                    formatC(as.integer(dot.coord[, categ[2]]), width = nchar(max(as.integer(dot.coord[, categ[2]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
-                )), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
-                }) # for tidy dot plots
-            # tidy_group_coord is to be able to fuse table when creating the table for dot coordinates
-            dot.coord <- data.frame(dot.coord, tidy_group_coord = dot.coord$group, stringsAsFactors = TRUE)
-        }
-    }
-    if( ! (identical(dot.coord$y, dot.coord$y.check) & identical(dot.coord$group, dot.coord$categ.check))){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\n(dot.coord$y AND dot.coord$y.check) AS WELL AS (dot.coord$group AND dot.coord$categ.check) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        if( ! identical(tempo.mean[order(tempo.mean$BOX, tempo.mean$PANEL), ]$BOX, unique(dot.coord[order(dot.coord$group, dot.coord$PANEL), c("group", "PANEL")])$group)){
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\n(tempo.mean$BOX, tempo.mean$PANEL) AND (dot.coord$group, dot.coord$PANEL) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            tempo <- unique(dot.coord[order(dot.coord$group, dot.coord$PANEL), c(categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){if(dot.categ != ini.dot.categ){dot.categ}}, if( ! is.null(facet.categ)){facet.categ}), drop = FALSE])
-            # names(tempo) <- paste0(names(tempo), ".mean")
-            tempo.mean <- data.frame(tempo.mean[order(tempo.mean$BOX, tempo.mean$PANEL), ], tempo, stringsAsFactors = TRUE)
-        }
-    }
-    # at that stage, categ color and dot color are correctly attributed in data1, box.coord and dot.coord
-    # end y dot coordinates recovery (create ini.box.coord, dot.coord and modify data1)
-    # ylim range
-    if(is.null(y.lim)){
-        y.lim <- tempo.graph.info.ini$layout$panel_params[[1]]$y.range # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-        if(any(( ! is.finite(y.lim)) | is.na(y.lim)) | length(y.lim) != 2){ # kept but normally no more Inf in data1 # normally no NA with is.finite, etc.
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\ntempo.graph.info.ini$layout$panel_params[[1]]$y.range[1] CONTAINS NA OR Inf OR HAS LENGTH 1")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }else if(y.log != "no"){
-        y.lim <- get(y.log)(y.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-    }
-    if(y.log != "no"){
-        # normally this control is not necessary anymore
-        if(any( ! is.finite(y.lim))){ # normally no NA with is.finite
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    if(suppressWarnings(all(y.lim %in% c(Inf, -Inf)))){ # all() without na.rm -> ok because y.lim cannot be NA (tested above)
-        # normally this control is not necessary anymore
-        tempo.cat <- paste0("ERROR IN ", function.name, " y.lim CONTAINS Inf VALUES, MAYBE BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY OR BECAUSE OF LOG SCALE REQUIREMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    if(suppressWarnings(any(is.na(y.lim)))){ # normally no NA with is.na
-        # normally this control is not necessary anymore
-        tempo.cat <- paste0("ERROR IN ", function.name, " y.lim CONTAINS NA OR NaN VALUES, MAYBE BECAUSE VALUES FROM data1 ARGUMENTS ARE NA OR Inf ONLY OR BECAUSE OF LOG SCALE REQUIREMENT")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    y.lim.order <- order(y.lim) # to deal with inverse axis
-    y.lim <- sort(y.lim)
-    y.lim[1] <- y.lim[1] - abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.bottom.extra.margin, y.top.extra.margin) # diff(y.lim.order) > 0 medians not inversed axis
-    y.lim[2] <- y.lim[2] + abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.top.extra.margin, y.bottom.extra.margin) # diff(y.lim.order) > 0 medians not inversed axis
-    if(y.include.zero == TRUE){ # no need to check y.log != "no" because done before
-        y.lim <- range(c(y.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    }
-    y.lim <- y.lim[y.lim.order]
-    if(any(is.na(y.lim))){ # normally no NA with is.na
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 2")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end ylim range
-    
-    
-    
-    
-    
-    
-    # drawing
-    # constant part
-    tempo.gg.name <- "gg.indiv.plot."
-    tempo.gg.count <- 0
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add is directly put here to deal with additional variable of data, like when using facet_grid. No problem if add is a theme, will be dealt below
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::xlab(if(is.null(x.lab)){categ[1]}else{x.lab}))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ylab(if(is.null(y.lab)){y}else{y.lab}))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
-    # text angle management
-    axis.just <- fun_gg_just(angle = x.angle, pos = ifelse(vertical == TRUE, "bottom", "left"), kind = "axis")
-    # end text angle management
-    add.check <- TRUE
-    if( ! is.null(add)){ # if add is NULL, then = 0
-        if(grepl(pattern = "ggplot2\\s*::\\s*theme", add) == TRUE){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT\n-> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER\n-> article ARGUMENT WILL BE IGNORED")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            add.check <- FALSE
-        }
-    }
-    if(add.check == TRUE & article == TRUE){
-        # WARNING: not possible to add theme()several times. NO message but the last one overwrites the others
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
-        if(grid == TRUE){
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-                text = ggplot2::element_text(size = text.size), 
-                plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-                line = ggplot2::element_line(size = 0.5), 
-                legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-                axis.line.y.left = ggplot2::element_line(colour = "black"), # draw lines for the y axis
-                axis.line.x.bottom = ggplot2::element_line(colour = "black"), # draw lines for the x axis
-                panel.grid.major.x = if(vertical == TRUE){NULL}else{ggplot2::element_line(colour = "grey85", size = 0.75)},
-                panel.grid.major.y = if(vertical == TRUE){ggplot2::element_line(colour = "grey85", size = 0.75)}else{NULL},
-                panel.grid.minor.y = if(vertical == TRUE){ggplot2::element_line(colour = "grey90", size = 0.25)}else{NULL},
-                axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
-                axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)},
-                strip.background = ggplot2::element_rect(fill = NA, colour = NA) # for facet background
-            ))
-        }else{
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-                text = ggplot2::element_text(size = text.size), 
-                plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-                line = ggplot2::element_line(size = 0.5), 
-                legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-                axis.line.y.left = ggplot2::element_line(colour = "black"), 
-                axis.line.x.bottom = ggplot2::element_line(colour = "black"),
-                axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
-                axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)},
-                strip.background = ggplot2::element_rect(fill = NA, colour = NA)
-            ))
-        }
-    }else if(add.check == TRUE & article == FALSE){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-            text = ggplot2::element_text(size = text.size), 
-            plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-            line = ggplot2::element_line(size = 0.5), 
-            legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-            panel.background = ggplot2::element_rect(fill = "grey95"), 
-            axis.line.y.left = ggplot2::element_line(colour = "black"), 
-            axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
-            panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
-            panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
-            panel.grid.minor.x = ggplot2::element_blank(), 
-            panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
-            strip.background = ggplot2::element_rect(fill = NA, colour = NA),
-            axis.text.x = if(vertical == TRUE){ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}else{NULL},
-            axis.text.y = if(vertical == TRUE){NULL}else{ggplot2::element_text(angle = axis.just$angle, hjust = axis.just$hjust, vjust = axis.just$vjust)}
-        ))
-    }
-    # Contrary to fun_gg_bar(), cannot plot the boxplot right now, because I need the dots plotted first
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, group = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), color = NA, width = box.width, fill = NA)) # this is to set the graph (i.e., a blanck boxplot to be able to use x coordinates to plot dots before boxes)
-    # end constant part
-    
-    
-    
-    
-    # graphic info recovery (including means)
-    tempo.graph.info <- ggplot2::ggplot_build(eval(parse(text = paste0(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, notch = box.notch, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}) + ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color})')))) # will be recovered later again, when ylim will be considered
-    tempo.yx.ratio <- (tempo.graph.info$layout$panel_params[[1]]$y.range[2] - tempo.graph.info$layout$panel_params[[1]]$y.range[1]) / (tempo.graph.info$layout$panel_params[[1]]$x.range[2] - tempo.graph.info$layout$panel_params[[1]]$x.range[1])
-    box.coord <- tempo.graph.info$data[[2]] # to have the summary statistics of the plot. Contrary to ini.box.plot, now integrates ylim Here because can be required for stat.pos when just box are plotted
-    box.coord$x <- as.numeric(box.coord$x) # because x is of special class that block comparison of values using identical
-    box.coord$PANEL <- as.numeric(box.coord$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
-    box.coord <- box.coord[order(box.coord$group, box.coord$PANEL), ]
-    if( ! (identical(tempo.mean$BOX, box.coord$group) & identical(tempo.mean$PANEL, box.coord$PANEL))){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nidentical(tempo.mean$BOX, box.coord$group) & identical(tempo.mean$PANEL, box.coord$PANEL) DO NOT HAVE THE SAME VALUE ORDER")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        # tempo <- c(categ, if( ! is.null(dot.color) & ! is.null(dot.categ)){if(dot.categ != ini.dot.categ){dot.categ}}, if( ! is.null(facet.categ)){facet.categ})
-        if(any(names(tempo.mean) %in% names(box.coord), na.rm = TRUE)){
-            names(tempo.mean)[names(tempo.mean) %in% names(box.coord)] <- paste0(names(tempo.mean)[names(tempo.mean) %in% names(box.coord)], ".mean")
-        }
-        box.coord <- data.frame(box.coord, tempo.mean, stringsAsFactors = TRUE)
-    }
-    # end graphic info recovery (including means)
-    
-    
-    
-    # stat output (will also serve for boxplot and mean display)
-    # x not added know to do not have them in stat.nolog
-    stat <- data.frame(
-        MIN = box.coord$ymin_final, 
-        QUART1 = box.coord$lower, 
-        MEDIAN = box.coord$middle, 
-        MEAN = box.coord$MEAN, 
-        QUART3 = box.coord$upper, 
-        MAX = box.coord$ymax_final, 
-        WHISK_INF = box.coord$ymin, 
-        BOX_INF = box.coord$lower, 
-        NOTCH_INF = box.coord$notchlower, 
-        NOTCH_SUP = box.coord$notchupper, 
-        BOX_SUP = box.coord$upper, 
-        WHISK_SUP = box.coord$ymax, 
-        OUTLIERS = box.coord["outliers"], 
-        tempo.mean[colnames(tempo.mean) != "MEAN"], 
-        COLOR = box.coord$fill, 
-        stringsAsFactors = TRUE
-    ) # box.coord["outliers"] written like this because it is a list. X coordinates not put now because several features to set
-    names(stat)[names(stat) == "outliers"] <- "OUTLIERS"
-    stat.nolog <- stat # stat.nolog ini will serve for outputs
-    if(y.log != "no"){
-        stat.nolog[c("MIN", "QUART1", "MEDIAN", "MEAN", "QUART3", "MAX", "WHISK_INF", "BOX_INF", "NOTCH_INF", "NOTCH_SUP", "BOX_SUP", "WHISK_SUP")] <- ifelse(y.log == "log2", 2, 10)^(stat.nolog[c("MIN", "QUART1", "MEDIAN", "MEAN", "QUART3", "MAX", "WHISK_INF", "BOX_INF", "NOTCH_INF", "NOTCH_SUP", "BOX_SUP", "WHISK_SUP")])
-        stat.nolog$OUTLIERS <- lapply(stat.nolog$OUTLIERS, FUN = function(X){ifelse(y.log == "log2", 2, 10)^X})
-    }
-    # end stat output (will also serve for boxplot and mean display)
-    
-    
-    
-    
-    
-    
-    # x coordinates management (for random plotting and for stat display)
-    # width commputations
-    width.ini <- c(box.coord$xmax - box.coord$xmin)[1] # all the box widths are equal here. Only the first one taken
-    width.correct <- width.ini * box.space / 2
-    if( ! (identical(stat$BOX, box.coord$group) & identical(stat$PANEL, box.coord$PANEL))){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nidentical(stat$BOX, box.coord$group) & identical(stat$PANEL, box.coord$PANEL) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        stat <- data.frame(
-            stat, 
-            X = box.coord$x, 
-            X_BOX_INF = box.coord$xmin + width.correct, 
-            X_BOX_SUP = box.coord$xmax - width.correct, 
-            X_NOTCH_INF = box.coord$x - (box.coord$x - (box.coord$xmin + width.correct)) / 2, 
-            X_NOTCH_SUP = box.coord$x + (box.coord$x - (box.coord$xmin + width.correct)) / 2, 
-            X_WHISK_INF = box.coord$x - (box.coord$x - (box.coord$xmin + width.correct)) * box.whisker.width, 
-            X_WHISK_SUP = box.coord$x + (box.coord$x - (box.coord$xmin + width.correct)) * box.whisker.width, 
-            # tempo.mean[colnames(tempo.mean) != "MEAN"], # already added above
-            stringsAsFactors = TRUE
-        )
-        stat$COLOR <- factor(stat$COLOR, levels = unique(categ.color))
-        if( ! all(stat$NOTCH_SUP < stat$BOX_SUP & stat$NOTCH_INF > stat$BOX_INF, na.rm = TRUE) & box.notch == TRUE){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") SOME NOTCHES ARE BEYOND BOX HINGES. TRY ARGUMENT box.notch = FALSE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    dot.jitter <- c((box.coord$xmax - width.correct) - (box.coord$xmin + width.correct))[1] * dot.jitter # real dot.jitter. (box.coord$xmin + width.correct) - (box.coord$xmax - width.correct))[1] is the width of the box. Is equivalent to (box.coord$x - (box.coord$xmin + width.correct))[1] * 2
-    # end width commputations
-    if( ! is.null(dot.color)){
-        # random dots
-        if(dot.tidy == FALSE){
-            dot.coord.rd1 <- merge(dot.coord, box.coord[c("fill", "PANEL", "group", "x")], by = c("PANEL", "group"), sort = FALSE) # rd for random. Send the coord of the boxes into the coord data.frame of the dots (in the column x.y). WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in box.coord. Thus, no need to consider fill column
-            if(nrow(dot.coord.rd1) != nrow(dot.coord)){
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.rd1 DATA FRAME. CODE HAS TO BE MODIFIED")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            sampled.dot.jitter <- if(nrow(dot.coord.rd1)== 1L){runif(n = nrow(dot.coord.rd1), min = - dot.jitter / 2, max = dot.jitter / 2)}else{sample(x = runif(n = nrow(dot.coord.rd1), min = - dot.jitter / 2, max = dot.jitter / 2), size = nrow(dot.coord.rd1), replace = FALSE)}
-            dot.coord.rd2 <- data.frame(dot.coord.rd1, dot.x = dot.coord.rd1$x.y + sampled.dot.jitter, stringsAsFactors = TRUE) # set the dot.jitter thanks to runif and dot.jitter range. Then, send the coord of the boxes into the coord data.frame of the dots (in the column x.y)
-            if(length(categ)== 1L){
-                tempo.data1 <- unique(data.frame(data1[categ[1]], group = as.integer(data1[, categ[1]]), stringsAsFactors = TRUE)) # categ[1] is factor
-                names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
-                verif <- paste0(categ[1], ".check")
-            }else if(length(categ) == 2L){
-                tempo.data1 <- unique(
-                    data.frame(
-                        data1[c(categ[1], categ[2])], 
-                        group = as.integer(factor(paste0(
-                            formatC(as.integer(data1[, categ[2]]), width = nchar(max(as.integer(data1[, categ[2]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
-                            ".", 
-                            formatC(as.integer(data1[, categ[1]]), width = nchar(max(as.integer(data1[, categ[1]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
-                        )), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
-                    )
-                ) # categ[2] first if categ[2] is used to make the categories in ggplot and categ[1] is used to make the x-axis
-                names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
-                names(tempo.data1)[names(tempo.data1) == categ[2]] <- paste0(categ[2], ".check")
-                verif <- c(paste0(categ[1], ".check"), paste0(categ[2], ".check"))
-            }else{
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 3")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            dot.coord.rd3 <- merge(dot.coord.rd2, tempo.data1, by = intersect("group", "group"), sort = FALSE) # send the factors of data1 into coord. WARNING: I have replaced by = "group" by intersect("group", "group") because of an error due to wrong group group merging in dot.coord.rd3
-            if(nrow(dot.coord.rd3) != nrow(dot.coord) | ( ! fun_comp_2d(dot.coord.rd3[categ], dot.coord.rd3[verif])$identical.content)){
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.rd3 DATA FRAME. CODE HAS TO BE MODIFIED")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            # end random dots
-        }
-        # tidy dots
-        # coordinates are recovered during plotting (see dot.coord.tidy1 below)
-        # end tidy dots
-    }
-    # end x coordinates management (for random plotting and for stat display)
-    
-    
-    
-    
-    
-    # boxplot display before dot display if box.fill = TRUE
-    coord.names <- NULL
-    # creation of the data frame for (main box + legend) and data frame for means
-    if(box.notch == FALSE){
-        for(i3 in 1:length(categ)){
-            if(i3== 1L){
-                tempo.polygon <- data.frame(GROUPX = c(t(stat[, rep(categ[i3], 5)])), stringsAsFactors = TRUE)
-            }else{
-                tempo.polygon <- cbind(tempo.polygon, c(t(stat[, rep(categ[i3], 5)])), stringsAsFactors = TRUE)
-            }
-        }
-        names(tempo.polygon) <- categ
-        tempo.polygon <- data.frame(X = c(t(stat[, c("X_BOX_INF", "X_BOX_SUP", "X_BOX_SUP", "X_BOX_INF", "X_BOX_INF")])), Y = c(t(stat[, c("BOX_INF", "BOX_INF", "BOX_SUP", "BOX_SUP", "BOX_INF")])), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), BOX = as.character(c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX")]))), tempo.polygon, stringsAsFactors = TRUE)
-        if( ! is.null(facet.categ)){
-            for(i4 in 1:length(facet.categ)){
-                tempo.polygon <- data.frame(tempo.polygon, c(t(stat[, c(facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4])])), stringsAsFactors = TRUE)
-                names(tempo.polygon)[length(names(tempo.polygon))] <- facet.categ[i4]
-            }
-        }
-    }else{
-        for(i3 in 1:length(categ)){
-            if(i3== 1L){
-                tempo.polygon <- data.frame(GROUPX = c(t(stat[, rep(categ[i3], 11)])), stringsAsFactors = TRUE)
-            }else{
-                tempo.polygon <- cbind(tempo.polygon, c(t(stat[, rep(categ[i3], 11)])), stringsAsFactors = TRUE)
-            }
-        }
-        names(tempo.polygon) <- categ
-        tempo.polygon <- data.frame(X = c(t(stat[, c("X_BOX_INF", "X_BOX_SUP", "X_BOX_SUP", "X_NOTCH_SUP", "X_BOX_SUP", "X_BOX_SUP", "X_BOX_INF", "X_BOX_INF", "X_NOTCH_INF", "X_BOX_INF", "X_BOX_INF")])), Y = c(t(stat[, c("BOX_INF", "BOX_INF", "NOTCH_INF", "MEDIAN", "NOTCH_SUP", "BOX_SUP", "BOX_SUP", "NOTCH_SUP", "MEDIAN", "NOTCH_INF", "BOX_INF")])), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), BOX = as.character(c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX", "BOX")]))), tempo.polygon, stringsAsFactors = TRUE)
-        if( ! is.null(facet.categ)){
-            for(i4 in 1:length(facet.categ)){
-                tempo.polygon <- data.frame(tempo.polygon, c(t(stat[, c(facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4], facet.categ[i4])])), stringsAsFactors = TRUE)
-                names(tempo.polygon)[length(names(tempo.polygon))] <- facet.categ[i4]
-            }
-        }
-    }
-    tempo.polygon$COLOR <- factor(tempo.polygon$COLOR, levels = unique(categ.color))
-    if( ! is.null(categ.class.order)){
-        for(i3 in 1:length(categ)){
-            tempo.polygon[, categ[i3]] <- factor(tempo.polygon[, categ[i3]], levels = categ.class.order[[i3]])
-        }
-    }
-    # modified name of dot.categ column (e.g., "Categ1_DOT") must be included for boxplot using ridy dots
-    if( ! is.null(dot.color) & ! is.null(dot.categ)){
-        if(dot.categ != ini.dot.categ){
-            tempo.polygon <- data.frame(tempo.polygon, GROUPX = tempo.polygon[, ini.dot.categ], stringsAsFactors = TRUE)
-            names(tempo.polygon)[names(tempo.polygon) == "GROUPX"] <- dot.categ
-            
-        }
-    }
-    tempo.diamon.mean <- data.frame(X = c(t(stat[, c("X", "X_NOTCH_INF", "X", "X_NOTCH_SUP", "X")])), Y = c(t(cbind(stat["MEAN"] - (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stat["MEAN"], stat["MEAN"] + (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stat["MEAN"], stat["MEAN"] - (stat[, "X"] - stat[, "X_NOTCH_INF"]) * tempo.yx.ratio, stringsAsFactors = TRUE))), COLOR = c(t(stat[, c("COLOR", "COLOR", "COLOR", "COLOR", "COLOR")])), GROUP = c(t(stat[, c("BOX", "BOX", "BOX", "BOX", "BOX")])), stringsAsFactors = TRUE) # stringsAsFactors = TRUE for cbind() because stat["MEAN"] is a data frame. Otherwise, stringsAsFactors is not an argument for cbind() on vectors
-    if( ! is.null(facet.categ)){
-        for(i3 in 1:length(facet.categ)){
-            tempo.diamon.mean <- data.frame(tempo.diamon.mean, c(t(stat[, c(facet.categ[i3], facet.categ[i3], facet.categ[i3], facet.categ[i3], facet.categ[i3])])), stringsAsFactors = TRUE)
-            names(tempo.diamon.mean)[length(names(tempo.diamon.mean))] <- facet.categ[i3]
-        }
-    }
-    tempo.diamon.mean$COLOR <- factor(tempo.diamon.mean$COLOR, levels = unique(categ.color))
-    # end creation of the data frame for (main box + legend) and data frame for means
-    if(box.fill == TRUE){
-        # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[length(categ)], fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, size = box.line.size, notch = box.notch, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}, alpha = box.alpha, outlier.shape = if( ! is.null(dot.color)){NA}else{21}, outlier.color = if( ! is.null(dot.color)){NA}else{dot.border.color}, outlier.fill = if( ! is.null(dot.color)){NA}else{NULL}, outlier.size = if( ! is.null(dot.color)){NA}else{dot.size}, outlier.stroke = if( ! is.null(dot.color)){NA}else{dot.border.size}, outlier.alpha = if( ! is.null(dot.color)){NA}else{dot.alpha})) # the color, size, etc. of the outliers are dealt here. outlier.color = NA to do not plot outliers when dots are already plotted. Finally, boxplot redrawn (see below)
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_polygon(
-            data = tempo.polygon, 
-            mapping = ggplot2::aes_string(x = "X", y = "Y", group = "BOX", fill = categ[length(categ)], color = categ[length(categ)]), 
-            size = box.line.size, 
-            alpha = box.alpha # works only for fill, not for color
-        ))
-        coord.names <- c(coord.names, "main.box")
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "sup.whisker")
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_INF, yend = WHISK_INF, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "inf.whisker")
-        if(box.whisker.width > 0){
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha, lineend = "round")) # 
-            coord.names <- c(coord.names, "sup.whisker.edge")
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_INF, yend = WHISK_INF, group = categ[length(categ)]), color = "black", size = box.line.size, alpha = box.alpha, lineend = "round")) # 
-            coord.names <- c(coord.names, "inf.whisker.edge")
-        }
-        if(box.mean == TRUE){
-            # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = stat, mapping = ggplot2::aes_string(x = "X", y = "MEAN", group = categ[length(categ)]), shape = 23, stroke = box.line.size * 2, fill = stat$COLOR, size = box.mean.size, color = "black", alpha = box.alpha)) # group used in aesthetic to do not have it in the legend
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_polygon(
-                data = tempo.diamon.mean, 
-                mapping = ggplot2::aes(x = X, y = Y, group = GROUP), 
-                fill = tempo.diamon.mean[, "COLOR"], 
-                color = hsv(0, 0, 0, alpha = box.alpha), # outline of the polygon in black but with alpha
-                size = box.line.size, 
-                alpha = box.alpha
-            ))
-            coord.names <- c(coord.names, "mean")
-        }
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = if(box.notch == FALSE){X_BOX_INF}else{X_NOTCH_INF}, xend = if(box.notch == FALSE){X_BOX_SUP}else{X_NOTCH_SUP}, y = MEDIAN, yend = MEDIAN, group = categ[length(categ)]), color = "black", size = box.line.size * 2, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "median")
-    }
-    # end boxplot display before dot display if box.fill = TRUE
-    
-    
-    
-    
-    
-    
-    # dot display
-    if( ! is.null(dot.color)){
-        if(dot.tidy == FALSE){
-            if(is.null(dot.categ)){
-                if(dot.border.size == 0){
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
-                        data = dot.coord.rd3, 
-                        mapping = ggplot2::aes_string(x = "dot.x", y = "y", group = categ[length(categ)]), 
-                        size = dot.size, 
-                        shape = 19, 
-                        color = dot.coord.rd3$dot.color, 
-                        alpha = dot.alpha
-                    )) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
-                }else{
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
-                        data = dot.coord.rd3, 
-                        mapping = ggplot2::aes_string(x = "dot.x", y = "y", group = categ[length(categ)]), 
-                        shape = 21, 
-                        stroke = dot.border.size, 
-                        color = if(is.null(dot.border.color)){dot.coord.rd3$dot.color}else{rep(dot.border.color, nrow(dot.coord.rd3))}, 
-                        size = dot.size, 
-                        fill = dot.coord.rd3$dot.color, 
-                        alpha = dot.alpha
-                    )) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
-                }
-            }else{
-                if(dot.border.size == 0){
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
-                        data = dot.coord.rd3, 
-                        mapping = ggplot2::aes_string(x = "dot.x", y = "y", alpha = dot.categ), 
-                        size = dot.size, 
-                        shape = 19, 
-                        color = dot.coord.rd3$dot.color
-                    )) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
-                }else{
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(
-                        data = dot.coord.rd3, 
-                        mapping = ggplot2::aes_string(x = "dot.x", y = "y", alpha = dot.categ), 
-                        size = dot.size, 
-                        shape = 21, 
-                        stroke = dot.border.size, 
-                        color = if(is.null(dot.border.color)){dot.coord.rd3$dot.color}else{rep(dot.border.color, nrow(dot.coord.rd3))}, 
-                        fill = dot.coord.rd3$dot.color
-                    )) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = dot.legend.name, values = rep(dot.alpha, length(dot.categ.class.order)), guide = ggplot2::guide_legend(override.aes = list(fill = dot.color, color = if(is.null(dot.border.color)){dot.color}else{dot.border.color}, stroke = dot.border.size, alpha = dot.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-            }
-            coord.names <- c(coord.names, "dots")
-        }else if(dot.tidy == TRUE){
-            # here plot using group -> no scale
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_dotplot(
-                data = dot.coord, 
-                mapping = ggplot2::aes_string(x = categ[1], y = "y", group = "group"), # not dot.categ here because the classes of dot.categ create new separations
-                position = ggplot2::position_dodge(width = box.width), 
-                binpositions = "all", 
-                binaxis = "y", 
-                stackdir = "center", 
-                alpha = dot.alpha, 
-                fill = dot.coord$dot.color, 
-                stroke = dot.border.size, 
-                color = if(is.null(dot.border.color)){dot.coord$dot.color}else{rep(dot.border.color, nrow(dot.coord))}, 
-                show.legend = FALSE, # WARNING: do not use show.legend = TRUE because it uses the arguments outside aes() as aesthetics (here color and fill). Thus I must find a way using ggplot2::scale_discrete_manual()
-                binwidth = (y.lim[2] - y.lim[1]) / dot.tidy.bin.nb
-            )) # geom_dotplot ggplot2 v3.3.0: I had to remove rev() in fill and color # very weird behavior of geom_dotplot ggplot2 v3.2.1, (1) because with aes group = (to avoid legend), the dot plotting is not good in term of coordinates, and (2) because data1 seems reorderer according to x = categ[1] before plotting. Thus, I have to use fill = dot.coord[rev(order(dot.coord[, categ[1]], decreasing = TRUE)), "dot.color"] to have the good corresponding colors # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
-            coord.names <- c(coord.names, "dots")
-            if( ! is.null(dot.categ)){
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_dotplot(
-                    data = dot.coord, 
-                    mapping = ggplot2::aes_string(x = categ[1], y = "y", alpha = dot.categ), # not dot.categ here because the classes of dot.categ create new separations
-                    position = ggplot2::position_dodge(width = box.width), 
-                    binpositions = "all", 
-                    binaxis = "y", 
-                    stackdir = "center", 
-                    fill = NA, 
-                    stroke = NA, 
-                    color = NA, 
-                    # WARNING: do not use show.legend = TRUE because it uses the arguments outside aes() as aesthetics (here color and fill). Thus I must find a way using ggplot2::scale_discrete_manual()
-                    binwidth = (y.lim[2] - y.lim[1]) / dot.tidy.bin.nb
-                )) # geom_dotplot ggplot2 v3.3.0: I had to remove rev() in fill and color # very weird behavior of geom_dotplot ggplot2 v3.2.1, (1) because with aes group = (to avoid legend), the dot plotting is not good in term of coordinates, and (2) because data1 seems reorderer according to x = categ[1] before plotting. Thus, I have to use fill = dot.coord[rev(order(dot.coord[, categ[1]], decreasing = TRUE)), "dot.color"] to have the good corresponding colors # show.legend option do not remove the legend, only the aesthetic of the legend (dot, line, etc.)
-                # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "linetype", name = dot.legend.name, values = rep(1, length(categ.color)))) # values = rep("black", length(categ.color)) are the values of color (which is the border color of dots), and this modify the border color on the plot. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-                coord.names <- c(coord.names, "bad_remove")
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = dot.legend.name, values = rep(dot.alpha, length(dot.categ.class.order)), labels = dot.categ.class.order, guide = ggplot2::guide_legend(title = if(ini.dot.categ == categ[length(categ)]){dot.categ}else{ini.dot.categ}, override.aes = list(fill = levels(dot.coord$dot.color), color = if(is.null(dot.border.color)){levels(dot.coord$dot.color)}else{dot.border.color}, stroke = dot.border.size, alpha = dot.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-            }
-            # coordinates of tidy dots
-            tempo.coord <- ggplot2::ggplot_build(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "))))$data # to have the tidy dot coordinates
-            if(length(which(sapply(X = tempo.coord, FUN = function(X){any(names(X) == "binwidth", na.rm = TRUE)}))) != 1){ # detect the compartment of tempo.coord which is the binned data frame
-                # if(length(which(sapply(tempo.coord, FUN = nrow) == nrow(data1))) > if(is.null(dot.categ)){1}else{2}){ # this does not work if only one dot per class, thus replaced by above # if(is.null(dot.categ)){1}else{2} because 1 dotplot if dot.categ is NULL and 2 dotplots if not, with the second being a blank dotplot with wrong coordinates. Thus take the first in that situation
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nEITHER MORE THAN 1 OR NO COMPARTMENT HAVING A DATA FRAME WITH binwidth AS COLUMN NAME IN THE tempo.coord LIST (FOR TIDY DOT COORDINATES). CODE HAS TO BE MODIFIED")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }else{
-                # dot.coord.tidy1 <- tempo.coord[[which(sapply(tempo.coord, FUN = nrow) == nrow(data1))[1]]] # this does not work if only one dot per class, thus replaced by above # the second being a blank dotplot with wrong coordinates. Thus take the first whatever situation
-                dot.coord.tidy1 <- tempo.coord[[which(sapply(X = tempo.coord, FUN = function(X){any(names(X) == "binwidth", na.rm = TRUE)}))]] # detect the compartment of tempo.coord which is the binned data frame
-                dot.coord.tidy1$x <- as.numeric(dot.coord.tidy1$x) # because weird class
-                dot.coord.tidy1$PANEL <- as.numeric(dot.coord.tidy1$PANEL) # because numbers as levels. But may be a problem is facet are reordered ?
-            }
-            # tempo.box.coord <- merge(box.coord, unique(dot.coord[, c("PANEL", "group", categ)]), by = c("PANEL", "group"), sort = FALSE) # not required anymore because box.coord already contains categ do not add dot.categ and tidy_group_coord here because the coordinates are for stats. Add the categ in box.coord. WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in box.coord. Thus, no need to consider fill column
-            # below inactivated because not true when dealing with dot.categ different from categ
-            # if(nrow(tempo.box.coord) != nrow(box.coord)){
-            # tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT tempo.box.coord DATA FRAME. CODE HAS TO BE MODIFIED")
-            # stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-            # }
-            dot.coord.tidy2 <- merge(dot.coord.tidy1, box.coord[c("fill", "PANEL", "group", "x", categ)], by = c("PANEL", "group"), sort = FALSE) # send the coord of the boxes into the coord data.frame of the dots (in the column x.y).WARNING: by = c("PANEL", "group") without fill column because PANEL & group columns are enough as only one value of x column per group number in tempo.box.coord. Thus, no need to consider fill colum # DANGER: from here the fill.y and x.y (from tempo.box.coord) are not good in dot.coord.tidy2. It is ok because Categ1 Categ2 from tempo.box.coord are ok with the group column from dot.coord.tidy1. This is due to the fact that dot.coord.tidy resulting from geom_dotplot does not make the same groups as the other functions
-            if(nrow(dot.coord.tidy2) != nrow(dot.coord)){
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.tidy2 DATA FRAME. CODE HAS TO BE MODIFIED")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            # From here, check for dot.coord.tidy3 which wil be important for stat over the plot. WARNING: dot.categ has nothing to do here for stat coordinates. Thus, not in tempo.data1
-            if(length(categ)== 1L){
-                tempo.data1 <- unique(data.frame(data1[categ[1]], group = as.integer(data1[, categ[1]]), stringsAsFactors = TRUE)) # categ[1] is factor
-                names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
-                verif <- paste0(categ[1], ".check")
-            }else if(length(categ) == 2L){
-                tempo.data1 <- unique(
-                    data.frame(
-                        data1[c(categ[1], categ[2])], 
-                        group = as.integer(factor(paste0(
-                            formatC(as.integer(data1[, categ[2]]), width = nchar(max(as.integer(data1[, categ[2]]), na.rm = TRUE)), flag = "0"), # convert factor into numeric with leading zero for proper ranking
-                            ".", 
-                            formatC(as.integer(data1[, categ[1]]), width = nchar(max(as.integer(data1[, categ[1]]), na.rm = TRUE)), flag = "0")# convert factor into numeric with leading zero for proper ranking
-                        )), stringsAsFactors = TRUE) # merge the 2 formatC() to create a new factor. The convertion to integer should recreate the correct group number
-                    )
-                ) # categ[2] first if categ[2] is used to make the categories in ggplot and categ[1] is used to make the x-axis
-                names(tempo.data1)[names(tempo.data1) == categ[1]] <- paste0(categ[1], ".check")
-                names(tempo.data1)[names(tempo.data1) == categ[2]] <- paste0(categ[2], ".check")
-                verif <- c(paste0(categ[1], ".check"), paste0(categ[2], ".check"))
-            }else{
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 4")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            dot.coord.tidy3 <- merge(dot.coord.tidy2, tempo.data1, by = intersect("group", "group"), sort = FALSE) # send the factors of data1 into coord. WARNING: I have tested intersect("group", "group") instead of by = "group". May be come back to by = "group" in case of error. But I did this because of an error in dot.coord.rd3 above
-            if(nrow(dot.coord.tidy3) != nrow(dot.coord) | ( ! fun_comp_2d(dot.coord.tidy3[categ], dot.coord.tidy3[verif])$identical.content)){
-                tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nTHE merge() FUNCTION DID NOT RETURN A CORRECT dot.coord.tidy3 DATA FRAME. CODE HAS TO BE MODIFIED")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-            }
-            # end coordinates of tidy dots
-        }
-    }
-    # end dot display
-    
-    
-    
-    # boxplot display (if box.fill = FALSE, otherwise, already plotted above)
-    if(box.fill == TRUE){
-        # overcome "work only for the filling of boxes, not for the frame. See https://github.com/tidyverse/ggplot2/issues/252"
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color}, guide = ggplot2::guide_legend(order = 1))) #, guide = ggplot2::guide_legend(override.aes = list(fill = levels(tempo.polygon$COLOR), color = "black")))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = rep(hsv(0, 0, 0, alpha = box.alpha), length(unique(data1[, categ[length(categ)]]))), guide = ggplot2::guide_legend(order = 1))) # , guide = ggplot2::guide_legend(override.aes = list(color = "black", alpha = box.alpha)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor # outline of the polygon in black but with alpha
-    }else{
-        # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_boxplot(data = data1, mapping = ggplot2::aes_string(x = categ[1], y = y, color = categ[length(categ)], fill = categ[length(categ)]), position = ggplot2::position_dodge(width = NULL), width = box.width, size = box.line.size, notch = box.notch, alpha = box.alpha, coef = if(box.whisker.kind == "no"){0}else if(box.whisker.kind == "std"){1.5}else if(box.whisker.kind == "max"){Inf}, outlier.shape = if( ! is.null(dot.color)){NA}else{21}, outlier.color = if( ! is.null(dot.color)){NA}else{if(dot.border.size == 0){NA}else{dot.border.color}}, outlier.fill = if( ! is.null(dot.color)){NA}else{NULL}, outlier.size = if( ! is.null(dot.color)){NA}else{dot.size}, outlier.stroke = if( ! is.null(dot.color)){NA}else{dot.border.size}, outlier.alpha = if( ! is.null(dot.color)){NA}else{dot.alpha})) # the color, size, etc. of the outliers are dealt here. outlier.color = NA to do not plot outliers when dots are already plotted
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_path(
-            data = tempo.polygon, 
-            mapping = ggplot2::aes_string(x = "X", y = "Y", group = "BOX", color = categ[length(categ)]), 
-            size = box.line.size, 
-            alpha = box.alpha, 
-            lineend = "round", 
-            linejoin = "round"
-        ))
-        coord.names <- c(coord.names, "main.box")
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = if(box.notch == FALSE){X_BOX_INF}else{X_NOTCH_INF}, xend = if(box.notch == FALSE){X_BOX_SUP}else{X_NOTCH_SUP}, y = MEDIAN, yend = MEDIAN, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size * 2, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "median")
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "sup.whisker")
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X, xend = X, y = BOX_INF, yend = WHISK_INF, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha)) # 
-        coord.names <- c(coord.names, "inf.whisker")
-        if(box.whisker.width > 0){
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_SUP, yend = WHISK_SUP, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha, lineend = "round")) # 
-            coord.names <- c(coord.names, "sup.whisker.edge")
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_segment(data = stat, mapping = ggplot2::aes(x = X_WHISK_INF, xend = X_WHISK_SUP, y = WHISK_INF, yend = WHISK_INF, group = categ[length(categ)]), color = stat$COLOR, size = box.line.size, alpha = box.alpha, lineend = "round")) # 
-            coord.names <- c(coord.names, "inf.whisker.edge")
-        }
-        if(box.mean == TRUE){
-            # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_point(data = stat, mapping = ggplot2::aes_string(x = "X", y = "MEAN", group = categ[length(categ)]), shape = 23, stroke = box.line.size * 2, color = stat$COLOR, size = box.mean.size, fill = NA, alpha = box.alpha)) # group used in aesthetic to do not have it in the legend. Here ggplot2::scale_discrete_manual() cannot be used because of the group easthetic
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_path(
-                data = tempo.diamon.mean, 
-                mapping = ggplot2::aes(x = X, y = Y, group = GROUP), 
-                color = tempo.diamon.mean[, "COLOR"], 
-                size = box.line.size, 
-                alpha = box.alpha, 
-                lineend = "round", 
-                linejoin = "round"
-            ))
-            coord.names <- c(coord.names, "mean")
-        }
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "fill", name = box.legend.name, values = rep(NA, length(unique(data1[, categ[length(categ)]]))))) #, guide = ggplot2::guide_legend(override.aes = list(color = categ.color)))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "color", name = box.legend.name, values = if(length(categ.color)== 1L){rep(categ.color, length(unique(data1[, categ[length(categ)]])))}else{categ.color}, guide = ggplot2::guide_legend(override.aes = list(alpha = if(plot == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list()) == 0L & Sys.info()["sysname"] == "Windows"))){1}else{box.alpha})))) # , guide = ggplot2::guide_legend(override.aes = list(color = as.character(categ.color))))) # values are the values of color (which is the border color in geom_box. WARNING: values = categ.color takes the numbers to make the colors if categ.color is a factor
-        if(plot == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list()) == 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-            # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    if(box.alpha == 0){ # remove box legend because no boxes drawn
-        # add this after the scale_xxx_manual() for boxplots
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE)) # inactivate the legend
-    }
-    # end boxplot display (if box.fill = FALSE, otherwise, already plotted above)
-    
-    
-    
-    
-    # stat display
-    # layer after dots but ok, behind dots on the plot
-    if( ! is.null(stat.pos)){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NUMBERS DISPLAYED ARE ", ifelse(stat.mean == FALSE, "MEDIANS", "MEANS"))
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        if(stat.pos == "top"){
-            tempo.stat <- data.frame(stat, Y = y.lim[2], stringsAsFactors = TRUE) # I had to create a data frame for geom_tex() so that facet is taken into account, (ggplot2::annotate() does not deal with facet because no data and mapping arguments). Of note, facet.categ is in tempo.stat, via tempo.mean, via dot.coord
-            if(stat.mean == FALSE){tempo.stat$MEDIAN <- formatC(stat.nolog$MEDIAN, digit = 2, drop0trailing = TRUE, format = "f")}else{tempo.stat$MEAN <- formatC(stat.nolog$MEAN, digit = 2, drop0trailing = TRUE, format = "f")}
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
-                data = tempo.stat, 
-                mapping = ggplot2::aes_string(x = "X", y = "Y", label = ifelse(stat.mean == FALSE, "MEDIAN", "MEAN")),
-                size = stat.size, 
-                color = "black", 
-                angle = stat.angle, 
-                hjust = stat.just$hjust, 
-                vjust = stat.just$vjust
-            )) # stat$X used here because identical to stat.nolog but has the X. WARNING: no need of order() for labels because box.coord$x set the order. For justification, see https://stackoverflow.com/questions/7263849/what-do-hjust-and-vjust-do-when-making-a-plot-using-ggplot
-            coord.names <- c(coord.names, "stat.pos")
-        }else if(stat.pos == "above"){
-            # stat coordinates
-            if( ! is.null(dot.color)){ # for text just above max dot
-                if(dot.tidy == FALSE){
-                    tempo.stat.ini <- dot.coord.rd3
-                }else if(dot.tidy == TRUE){
-                    tempo.stat.ini <- dot.coord.tidy3
-                    tempo.stat.ini$x.y <- tempo.stat.ini$x.x # this is just to be able to use tempo.stat.ini$x.y for untidy or tidy dots (remember that dot.coord.tidy3$x.y is not good, see above)
-                }
-                stat.coord1 <- aggregate(x = tempo.stat.ini["y"], by = {x.env <- if(length(categ)== 1L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]])}else if(length(categ) == 2L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]], tempo.stat.ini[, categ[2]])} ; names(x.env) <- if(length(categ)== 1L){c("group", "PANEL", "x.y", categ[1])}else if(length(categ) == 2L){c("group", "PANEL", "x.y", categ[1], categ[2])} ; x.env}, FUN = min, na.rm = TRUE)
-                names(stat.coord1)[names(stat.coord1) == "y"] <- "dot.min"
-                stat.coord2 <- aggregate(x = tempo.stat.ini["y"], by = {x.env <- if(length(categ)== 1L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]])}else if(length(categ) == 2L){list(tempo.stat.ini$group, tempo.stat.ini$PANEL, tempo.stat.ini$x.y, tempo.stat.ini[, categ[1]], tempo.stat.ini[, categ[2]])} ; names(x.env) <- if(length(categ)== 1L){c("group", "PANEL", "x.y", categ[1])}else if(length(categ) == 2L){c("group", "PANEL", "x.y", categ[1], categ[2])} ; x.env}, FUN = max, na.rm = TRUE)
-                names(stat.coord2) <- paste0(names(stat.coord2), "_from.dot.max")
-                names(stat.coord2)[names(stat.coord2) == "y_from.dot.max"] <- "dot.max"
-                stat.coord3 <- cbind(box.coord[order(box.coord$group, box.coord$PANEL), ], stat.coord1[order(stat.coord1$group, stat.coord1$x.y), ], stat.coord2[order(stat.coord2$group, stat.coord2$x.y), ], stringsAsFactors = TRUE) # 
-                if( ! all(identical(round(stat.coord3$x, 9), round(as.numeric(stat.coord3$x.y), 9)), na.rm = TRUE)){ # as.numeric() because stat.coord3$x is class "mapped_discrete" "numeric"
-                    tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nFUSION OF box.coord, stat.coord1 AND stat.coord2 ACCORDING TO box.coord$x, stat.coord1$x.y AND stat.coord2$x.y IS NOT CORRECT. CODE HAS TO BE MODIFIED")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }
-                # text.coord <- stat.coord3[, c("x", "group", "dot.min", "dot.max")]
-                # names(text.coord)[names(text.coord) == "dot.min"] <- "text.min.pos"
-                #names(text.coord)[names(text.coord) == "dot.max"] <- "text.max.pos"
-                box.coord <- box.coord[order(box.coord$x, box.coord$group, box.coord$PANEL), ]
-                # text.coord <- text.coord[order(text.coord$x), ] # to be sure to have the two objects in the same order for x. WARNING: cannot add identical(as.integer(text.coord$group), as.integer(box.coord$group)) because with error, the correspondence between x and group is not the same
-                stat.coord3 <- stat.coord3[order(stat.coord3$x, stat.coord3$group, stat.coord3$PANEL), ] # to be sure to have the two objects in the same order for x. WARNING: cannot add identical(as.integer(text.coord$group), as.integer(box.coord$group)) because with error, the correspondence between x and group is not the same
-                if( ! (identical(box.coord$x, stat.coord3$x) & identical(box.coord$group, stat.coord3$group) & identical(box.coord$PANEL, stat.coord3$PANEL))){
-                    tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\ntext.coord AND box.coord DO NOT HAVE THE SAME x, group AND PANEL COLUMN CONTENT")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-                }
-            }else{
-                stat.coord3 <- box.coord
-            }
-            stat.coord3 <- data.frame(
-                stat.coord3, 
-                Y = stat.coord3[, ifelse(
-                    is.null(dot.color), 
-                    ifelse(diff(y.lim) > 0, "ymax", "ymin"), 
-                    ifelse(diff(y.lim) > 0, "ymax_final", "ymin_final")
-                )], 
-                stringsAsFactors = TRUE
-            ) # ymax is top whisker, ymax_final is top dot
-            # stat.coord3 <- data.frame(stat.coord3, Y = vector("numeric", length = nrow(stat.coord3)), stringsAsFactors = TRUE)
-            # check.Y <- as.logical(stat.coord3$Y) # convert everything in Y into FALSE (because Y is full of zero)
-            # end stat coordinates
-            # stat display
-            # performed twice: first for y values >=0, then y values < 0, because only a single value allowed for hjust anf vjust
-            if(stat.mean == FALSE){
-                tempo.center.ref <- "middle"
-            }else{
-                tempo.center.ref <- "MEAN"
-            }
-            # if(is.null(dot.color)){
-            # tempo.low.ref <- "ymin"
-            # tempo.high.ref <- "ymax"
-            # }else{
-            # tempo.low.ref <- "ymin_final"
-            # tempo.high.ref <- "ymax_final"
-            # }
-            # tempo.log.high <- if(diff(y.lim) > 0){stat.coord3[, tempo.center.ref] >= 0}else{stat.coord3[, tempo.center.ref] < 0}
-            # tempo.log.low <- if(diff(y.lim) > 0){stat.coord3[, tempo.center.ref] < 0}else{stat.coord3[, tempo.center.ref] >= 0}
-            # stat.coord3$Y[tempo.log.high] <- stat.coord3[tempo.log.high, tempo.high.ref]
-            # stat.coord3$Y[tempo.log.low] <- stat.coord3[tempo.log.low, tempo.low.ref]
-            # add distance
-            stat.coord3$Y <- stat.coord3$Y + diff(y.lim) * stat.dist / 100
-            # end add distance
-            # correct median or mean text format
-            if(y.log != "no"){
-                stat.coord3[, tempo.center.ref] <- ifelse(y.log == "log2", 2, 10)^(stat.coord3[, tempo.center.ref])
-            }
-            stat.coord3[, tempo.center.ref] <- formatC(stat.coord3[, tempo.center.ref], digit = 2, drop0trailing = TRUE, format = "f")
-            # end correct median or mean text format
-            # if(any(tempo.log.high) == TRUE){
-            # tempo.stat <- stat.coord3[tempo.log.high,]
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
-                data = stat.coord3, 
-                mapping = ggplot2::aes_string(x = "x", y = "Y", label = tempo.center.ref),
-                size = stat.size, 
-                color = "black", 
-                angle = stat.angle, 
-                hjust = stat.just$hjust, 
-                vjust = stat.just$vjust
-            )) # WARNING: no need of order() for labels because box.coord$x set the order
-            coord.names <- c(coord.names, "stat.pos")
-            # }
-            # if(any(tempo.log.low) == TRUE){
-            # tempo.stat <- stat.coord3[tempo.log.low,]
-            # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::geom_text(
-            # data = tempo.stat, 
-            # mapping = ggplot2::aes_string(x = "x", y = "Y", label = tempo.center.ref),
-            # size = stat.size, 
-            # color = "black", 
-            # hjust = ifelse(vertical == TRUE, 0.5, 0.5 + stat.dist), 
-            # vjust = ifelse(vertical == TRUE, 0.5 + stat.dist, 0.5)
-            # )) # WARNING: no need of order() for labels because box.coord$x set the order
-            # coord.names <- c(coord.names, "stat.pos.negative")
-            # }
-            # end stat display
-        }else{
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 5")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-    }
-    # end stat display
-    # legend management
-    if(legend.show == FALSE){ # must be here because must be before bef.final.plot <- 
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE, alpha = FALSE)) # inactivate the initial legend
-    }
-    # end legend management
-    
-    
-    
-    # y scale management (cannot be before dot plot management)
-    # the rescaling aspect is complicated and not intuitive. See:
-    # explaination: https://github.com/tidyverse/ggplot2/issues/3948
-    # the oob argument of scale_y_continuous() https://ggplot2.tidyverse.org/reference/scale_continuous.html
-    # see also https://github.com/rstudio/cheatsheets/blob/master/data-visualization-2.1.pdf
-    # secondary ticks
-    bef.final.plot <- ggplot2::ggplot_build(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + if(vertical == TRUE){ggplot2::scale_y_continuous(expand = c(0, 0), limits = sort(y.lim), oob = scales::rescale_none)}else{ggplot2::coord_flip(ylim = y.lim)}')))) # here I do not need the x-axis and y-axis orientation, I just need the number of main ticks and the legend. I DI NOT UNDERSTAND THE COMMENT HERE BECAUSE WE NEED COORD_FLiP
-    tempo.coord <- bef.final.plot$layout$panel_params[[1]]
-    # y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non NULL or if y.log argument is different from "no")
-    if(y.log != "no"){ # integer main ticks for log2 and log10
-        tempo.scale <- (as.integer(min(y.lim, na.rm = TRUE)) - 1):(as.integer(max(y.lim, na.rm = TRUE)) + 1)
-    }else{
-        tempo <- if(is.null(attributes(tempo.coord$y$breaks))){tempo.coord$y$breaks}else{unlist(attributes(tempo.coord$y$breaks))}
-        if(all(is.na(tempo))){# all() without na.rm -> ok because is.na() cannot be NA
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$y$breaks")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }
-        tempo.scale <- fun_scale(lim = y.lim, n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks. If fact: n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) replaced by n = ifelse(is.null(y.tick.nb), 4, y.tick.nb))
-    }
-    y.second.tick.values <- NULL
-    y.second.tick.pos <- NULL
-    if(y.log != "no"){
-        tempo <- fun_inter_ticks(lim = y.lim, log = y.log)
-        y.second.tick.values <- tempo$values
-        y.second.tick.pos <- tempo$coordinates
-        # if(vertical == TRUE){ # do not remove in case the bug is fixed
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", y = y.second.tick.pos, yend = y.second.tick.pos, x = tempo.coord$x.range[1], xend = tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80))
-        # }else{ # not working because of the ggplot2 bug
-        # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", x = y.second.tick.pos, xend = y.second.tick.pos, y = tempo.coord$y.range[1], yend = tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80))
-        # }
-        coord.names <- c(coord.names, "y.second.tick.positions")
-    }else if(( ! is.null(y.second.tick.nb)) & y.log == "no"){
-        # if(y.second.tick.nb > 0){ #inactivated because already checked before
-        if(length(tempo.scale) < 2){
-            tempo.cat1 <- c("y.tick.nb", "y.second.tick.nb")
-            tempo.cat2 <- sapply(list(y.tick.nb, y.second.tick.nb), FUN = paste0, collapse = " ")
-            tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE Y-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            tempo <- fun_inter_ticks(lim = y.lim, log = y.log, breaks = tempo.scale, n = y.second.tick.nb)
-        }
-        y.second.tick.values <- tempo$values
-        y.second.tick.pos <- tempo$coordinates
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
-            geom = "segment", 
-            y = y.second.tick.pos, 
-            yend = y.second.tick.pos, 
-            x = if(vertical == TRUE){tempo.coord$x.range[1]}else{tempo.coord$y.range[1]}, 
-            xend = if(vertical == TRUE){tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80}else{tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80}
-        ))
-        coord.names <- c(coord.names, "y.second.tick.positions")
-    }
-    # end y.second.tick.positions
-    # for the ggplot2 bug with y.log, this does not work: eval(parse(text = ifelse(vertical == FALSE & y.log == "log10", "ggplot2::scale_x_continuous", "ggplot2::scale_y_continuous")))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_y_continuous(
-        breaks = tempo.scale, 
-        minor_breaks = y.second.tick.pos, 
-        labels = if(y.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(y.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(y.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 6") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, # == in stop() to be able to add several messages between ==
-        expand = c(0, 0), # remove space after after axis limits
-        limits = sort(y.lim), # NA indicate that limits must correspond to data limits but ylim() already used
-        oob = scales::rescale_none, 
-        trans = ifelse(diff(y.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_y_reverse() but create the problem of y-axis label disappearance with y.lim decreasing. Thus, do not use. Use ylim() below and after this
-    ))
-    if(vertical == TRUE){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_cartesian(ylim = y.lim)) # problem of ggplot2::ylim() is that it redraws new breaks # coord_cartesian(ylim = y.lim)) not used because bug -> y-axis label disappearance with y.lim decreasing I DO NOT UNDERSTAND THIS MESSAGE WHILE I USE COORD_CARTESIAN # clip = "off" to have secondary ticks outside plot region does not work
-    }else{
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_flip(ylim = y.lim)) # clip = "off" to have secondary ticks outside plot region does not work # create the problem of y-axis label disappearance with y.lim decreasing. IDEM ABOVE
-        
-    }
-    # end y scale management (cannot be before dot plot management)
-    
-    
-    # legend management
-    if( ! is.null(legend.width)){
-        legend.final <- fun_gg_get_legend(ggplot_built = bef.final.plot, fun.name = function.name, lib.path = lib.path) # get legend
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::guides(fill = FALSE, color = FALSE, alpha = FALSE)) # inactivate the initial legend
-        if(is.null(legend.final) & plot == TRUE){ # even if any(unlist(legend.disp)) is TRUE
-            legend.final <- ggplot2::ggplot()+ggplot2::theme_void() # empty graph instead of legend
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON NULL legend.width ARGUMENT\n")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end legend management
-    
-    
-    # drawing
-    fin.plot <- suppressMessages(suppressWarnings(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))))
-    grob.save <- NULL
-    if(plot == TRUE){
-        # following lines inactivated because of problem in warn.recov and message.recov
-        # assign("env_fun_get_message", new.env())
-        # assign("tempo.gg.name", tempo.gg.name, envir = env_fun_get_message)
-        # assign("tempo.gg.count", tempo.gg.count, envir = env_fun_get_message)
-        # assign("add", add, envir = env_fun_get_message)
-        # two next line: for the moment, I cannot prevent the warning printing
-        # warn.recov <- fun_get_message(paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}), kind = "warning", header = FALSE, print.no = FALSE, env = env_fun_get_message) # for recovering warnings printed by ggplot() functions
-        # message.recov <- fun_get_message('print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))', kind = "message", header = FALSE, print.no = FALSE, env = env_fun_get_message) # for recovering messages printed by ggplot() functions
-        # if( ! (return == TRUE & return.ggplot == TRUE)){ # because return() plots when return.ggplot is TRUE # finally not used -> see return.ggplot description
-        if(is.null(legend.width)){
-            grob.save <- suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot)))
-        }else{
-            grob.save <-suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
-        }
-        # }
-        # suppressMessages(suppressWarnings(print(eval(parse(text = paste(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), if(is.null(add)){NULL}else{add}))))))
-    }else{
-        # following lines inactivated because of problem in warn.recov and message.recov
-        # message.recov <- NULL
-        # warn.recov <- NULL
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    # end drawing
-    
-    
-    
-    # output
-    # following lines inactivated because of problem in warn.recov and message.recov
-    # if( ! (is.null(warn) & is.null(warn.recov) & is.null(message.recov))){
-    # warn <- paste0(warn, "\n\n", if(length(warn.recov) > 0 | length(message.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", ifelse( ! is.null(warn.recov), unique(message.recov), ""), ifelse( ! is.null(message.recov), unique(message.recov), ""), collapse = "\n\n"), "\n\n")})
-    # }else if( ! (is.null(warn) & is.null(warn.recov)) & is.null(message.recov)){
-    # warn <- paste0(warn, "\n\n", if(length(warn.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", unique(warn.recov), collapse = "\n\n"), "\n\n")})
-    # }else if( ! (is.null(warn) & is.null(message.recov)) & is.null(warn.recov)){
-    # warn <- paste0(warn, "\n\n", if(length(message.recov) > 0){paste0(paste0("MESSAGES FROM ggplot2 FUNCTIONS: ", unique(message.recov), collapse = "\n\n"), "\n\n")})
-    # }
-    if(warn.print == TRUE & ! is.null(warn)){
-        on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
-    }
-    on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
-    if(return == TRUE){
-        tempo.output <- ggplot2::ggplot_build(fin.plot)
-        tempo.output$data <- tempo.output$data[-1] # remove the first data because corresponds to the initial empty boxplot
-        if(length(tempo.output$data) != length(coord.names)){
-            tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nlength(tempo.output$data) AND length(coord.names) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-        }else{
-            names(tempo.output$data) <- coord.names
-            tempo.output$data <- tempo.output$data[coord.names != "bad_remove"]
-        }
-        tempo <- tempo.output$layout$panel_params[[1]]
-        output <- list(
-            data = data1.ini, 
-            stat = stat.nolog, 
-            removed.row.nb = removed.row.nb, 
-            removed.rows = removed.rows, 
-            plot = c(tempo.output$data, y.second.tick.values = list(y.second.tick.values)), 
-            panel = facet.categ, 
-            axes = list(
-                x.range = tempo$x.range, 
-                x.labels = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{tempo$x$scale$get_labels()}, # is.null(attributes(tempo$x$breaks)) test if it is number (TRUE) or character (FALSE)
-                x.positions = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{unlist(attributes(tempo$x$breaks))}, 
-                y.range = tempo$y.range, 
-                y.labels = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{tempo$y$scale$get_labels()}, 
-                y.positions = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{unlist(attributes(tempo$y$breaks))}
-            ), 
-            warn = paste0("\n", warn, "\n\n"), 
-            ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL}, # fin.plot plots the graph if return == TRUE
-            gtable = if(return.gtable == TRUE){grob.save}else{NULL} 
-        )
-        return(output) # this plots the graph if return.ggplot is TRUE and if no assignment
-    }
-    # end output
-    # end main code
+}else{
+for(i2 in 1:length(data1)){
+if(geom[[i2]] == "geom_point"){
+if(nrow(data1[[i2]]) <= raster.threshold){
+scatter.kind[[i2]] <- "ggplot2::geom_point"
+}else{
+scatter.kind[[i2]] <- "fun_gg_point_rast"
+fix.ratio <- TRUE
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i2, " OF data1 ARGUMENT")), " LAYER AS RASTER (NOT VECTORIAL)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
 }
+}
+}
+if(any(unlist(scatter.kind) == "fun_gg_point_rast")){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") RASTER PLOT GENERATED -> ASPECT RATIO OF THE PLOT REGION SET BY THE raster.ratio ARGUMENT (", fun_round(raster.ratio, 2), ") TO AVOID A BUG OF ELLIPSOID DOT DRAWING")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}
+# end kind of geom_point (vectorial or raster)
+
+
+
+
+# no need loop part
+coord.names <- NULL
+tempo.gg.name <- "gg.indiv.plot."
+tempo.gg.count <- 0
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::xlab(if(is.null(x.lab)){x[[1]]}else{x.lab}))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ylab(if(is.null(y.lab)){y[[1]]}else{y.lab}))
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
+# text angle management
+x.tempo.just <- fun_gg_just(angle = x.text.angle, pos = "bottom", kind = "axis")
+y.tempo.just <- fun_gg_just(angle = y.text.angle, pos = "left", kind = "axis")
+# end text angle management
+add.check <- TRUE
+if( ! is.null(add)){ # if add is NULL, then = 0
+if(grepl(pattern = "ggplot2::theme", add) == TRUE){
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT\n-> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER\n-> article ARGUMENT WILL BE IGNORED\nIT IS RECOMMENDED TO USE \"+ theme(aspect.ratio = raster.ratio)\" IF RASTER MODE IS ACTIVATED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+add.check <- FALSE
+}
+}
+if(add.check == TRUE & article == TRUE){
+# WARNING: not possible to add several times theme(). NO message but the last one overwrites the others
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
+if(grid == TRUE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+line = ggplot2::element_line(size = 0.5), 
+axis.line.y.left = ggplot2::element_line(colour = "black"), # draw lines for the y axis
+axis.line.x.bottom = ggplot2::element_line(colour = "black"), # draw lines for the x axis
+panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.minor.x = ggplot2::element_line(colour = "grey90", size = 0.25), 
+panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
+axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
+axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
+aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
+))
+}else{
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_line(size = 0.5), 
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+axis.line.y.left = ggplot2::element_line(colour = "black"), 
+axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
+axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
+axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
+aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
+))
+}
+}else if(add.check == TRUE & article == FALSE){
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
+text = ggplot2::element_text(size = text.size), 
+plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
+line = ggplot2::element_line(size = 0.5), 
+legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
+panel.background = ggplot2::element_rect(fill = "grey95"), 
+axis.line.y.left = ggplot2::element_line(colour = "black"), 
+axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
+panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.minor.x = ggplot2::element_line(colour = "grey90", size = 0.25), 
+panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
+panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
+strip.background = ggplot2::element_rect(fill = "white", colour = "black"), 
+axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
+axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
+aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
+# do not work -> legend.position = "none" # to remove the legend completely: https://www.datanovia.com/en/blog/how-to-remove-legend-from-a-ggplot/
+))
+}
+# end no need loop part
+
+
+# loop part
+point.count <- 0
+line.count <- 0
+lg.order <- vector(mode = "list", length = 6) # order of the legend
+lg.order <- lapply(lg.order, as.numeric) # order of the legend
+lg.color <- vector(mode = "list", length = 6) # color of the legend
+lg.dot.shape <- vector(mode = "list", length = 6) # etc.
+lg.dot.size <- vector(mode = "list", length = 6) # etc.
+lg.dot.size <- lapply(lg.dot.size, as.numeric) # etc.
+lg.dot.border.size <- vector(mode = "list", length = 6) # etc.
+lg.dot.border.size <- lapply(lg.dot.border.size, as.numeric) # etc.
+lg.dot.border.color <- vector(mode = "list", length = 6) # etc.
+lg.line.size <- vector(mode = "list", length = 6) # etc.
+lg.line.size <- lapply(lg.line.size, as.numeric) # etc.
+lg.line.type <- vector(mode = "list", length = 6) # etc.
+lg.alpha <- vector(mode = "list", length = 6) # etc.
+lg.alpha <- lapply(lg.alpha, as.numeric) # etc.
+for(i1 in 1:length(data1)){
+if(geom[[i1]] == "geom_point"){
+point.count <- point.count + 1
+if(point.count== 1L){
+fin.lg.disp[[1]] <- legend.disp[[point.count + line.count]]
+lg.order[[1]] <- point.count + line.count
+lg.color[[1]] <- color[[i1]] # if color == NULL -> NULL
+lg.dot.shape[[1]] <- dot.shape[[i1]]
+lg.dot.size[[1]] <- dot.size[[i1]]
+lg.dot.border.size[[1]] <- dot.border.size[[i1]]
+lg.dot.border.color[[1]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
+if(plot == TRUE & fin.lg.disp[[1]] == TRUE & dot.shape[[1]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[1]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[1]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], fill = categ[[i1]]), shape = dot.shape[[i1]], size = dot.size[[i1]], stroke = dot.border.size[[i1]], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = if(i5== 1L){TRUE}else{FALSE})) # WARNING: a single color allowed for color argument outside aesthetic, but here a single color for border --> loop could be inactivated but kept for commodity # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_fill_manual(name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = as.character(color[[i1]]), breaks = class.categ)) # values are the values of fill, breaks reorder the classes according to class.categ in the legend, order argument of guide_legend determines the order of the different aesthetics in the legend (not order of classes). See guide_legend settings of scale_..._manual below
+}
+if(point.count== 2L){
+fin.lg.disp[[2]] <- legend.disp[[point.count + line.count]]
+lg.order[[2]] <- point.count + line.count
+lg.color[[2]] <- color[[i1]] # if color == NULL -> NULL
+lg.dot.shape[[2]] <- dot.shape[[i1]]
+lg.dot.size[[2]] <- dot.size[[i1]]
+lg.dot.border.size[[2]] <- dot.border.size[[i1]]
+lg.dot.border.color[[2]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
+if(plot == TRUE & fin.lg.disp[[2]] == TRUE & dot.shape[[2]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[2]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[2]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], shape = categ[[i1]]), size = dot.size[[i1]], stroke = dot.border.size[[i1]], fill = color[[i1]][i5], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = FALSE)) # WARNING: a single color allowed for fill argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_shape_manual(name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(dot.shape[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of shape, breaks reorder the classes according to class.categ in the legend. See guide_legend settings of scale_..._manual below
 
+}
+if(point.count== 3L){
+fin.lg.disp[[3]] <- legend.disp[[point.count + line.count]]
+lg.order[[3]] <- point.count + line.count
+lg.color[[3]] <- color[[i1]] # if color == NULL -> NULL
+lg.dot.shape[[3]] <- dot.shape[[i1]]
+lg.dot.size[[3]] <- dot.size[[i1]]
+lg.dot.border.size[[3]] <- dot.border.size[[i1]]
+lg.dot.border.color[[3]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
+if(plot == TRUE & fin.lg.disp[[3]] == TRUE & dot.shape[[3]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[3]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[3]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], stroke = categ[[i1]]), shape = dot.shape[[i1]], size = dot.size[[i1]], fill = color[[i1]][i5], stroke = dot.border.size[[i1]], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = FALSE)) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "stroke", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(dot.border.size[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of stroke, breaks reorder the classes according to class.categ in the legend. See guide_legend settings of scale_..._manual below
 
+}
+}else{
+line.count <- line.count + 1
+if(line.count== 1L){
+fin.lg.disp[[4]] <- legend.disp[[point.count + line.count]]
+lg.order[[4]] <- point.count + line.count
+lg.color[[4]] <- color[[i1]] # if color == NULL -> NULL
+lg.line.size[[4]] <- line.size[[i1]]
+lg.line.type[[4]] <- line.type[[i1]]
+if(plot == TRUE & fin.lg.disp[[4]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[4]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[4]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
+ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
+"(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
+x[[i1]], 
+ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
+y[[i1]], 
+if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
+", linetype = ", 
+categ[[i1]], 
+"), color = \"", 
+color[[i1]][i5], 
+"\", size = ", 
+line.size[[i1]], 
+ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
+ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
+", alpha = ", 
+alpha[[i1]], 
+", show.legend = ", 
+ifelse(i5== 1L, TRUE, FALSE), 
+")"
+)))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "linetype", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(line.type[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, with different values, breaks reorder the classes according to class.categ in the legend
+}
+if(line.count== 2L){
+fin.lg.disp[[5]] <- legend.disp[[point.count + line.count]]
+lg.order[[5]] <- point.count + line.count
+lg.color[[5]] <- color[[i1]] # if color == NULL -> NULL
+lg.line.size[[5]] <- line.size[[i1]]
+lg.line.type[[5]] <- line.type[[i1]]
+if(plot == TRUE & fin.lg.disp[[5]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[5]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[5]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
+ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
+"(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
+x[[i1]], 
+ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
+y[[i1]], 
+if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
+", alpha = ", 
+categ[[i1]], 
+"), color = \"", 
+color[[i1]][i5], 
+"\", size = ", 
+line.size[[i1]], 
+", linetype = ", 
+ifelse(is.numeric(line.type[[i1]]), "", "\""), 
+line.type[[i1]], 
+ifelse(is.numeric(line.type[[i1]]), "", "\""), 
+ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
+ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
+", show.legend = FALSE)"
+)))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(alpha[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, with different values, breaks reorder the classes according to class.categ in the legend
+}
+if(line.count== 3L){
+fin.lg.disp[[6]] <- legend.disp[[point.count + line.count]]
+lg.order[[6]] <- point.count + line.count
+lg.color[[6]] <- color[[i1]] # if color == NULL -> NULL
+lg.line.size[[6]] <- line.size[[i1]]
+lg.line.type[[6]] <- line.type[[i1]]
+if(plot == TRUE & fin.lg.disp[[6]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+lg.alpha[[6]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
+}else{
+lg.alpha[[6]] <- alpha[[i1]]
+}
+class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
+for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
+tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
+ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
+"(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
+x[[i1]], 
+ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
+y[[i1]], 
+if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
+", size = ", 
+categ[[i1]], 
+"), color = \"", 
+color[[i1]][i5], 
+"\", linetype = ", 
+ifelse(is.numeric(line.type[[i1]]), "", "\""), 
+line.type[[i1]], 
+ifelse(is.numeric(line.type[[i1]]), "", "\""), 
+ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
+ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
+", alpha = ", 
+alpha[[i1]], 
+", show.legend = FALSE)"
+)))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
+coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
+}
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "size", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(line.size[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, breaks reorder the classes according to class.categ in the legend
+}
+}
+}
+# end loop part
 
 
 
-# add density
-# rasterise all kind: https://cran.r-project.org/web/packages/ggrastr/vignettes/Raster_geoms.html
-# log not good: do not convert as in boxplot
-
 
-fun_gg_scatter <- function(
-    data1, 
-    x, 
-    y, 
-    categ = NULL, 
-    categ.class.order = NULL, 
-    color = NULL, 
-    geom = "geom_point", 
-    geom.step.dir = "hv", 
-    geom.stick.base = NULL, 
-    alpha = 0.5, 
-    dot.size = 2, 
-    dot.shape = 21, 
-    dot.border.size = 0.5, 
-    dot.border.color = NULL, 
-    line.size = 0.5, 
-    line.type = "solid", 
-    x.lim = NULL, 
-    x.lab = NULL, 
-    x.log = "no", 
-    x.tick.nb = NULL, 
-    x.second.tick.nb = NULL, 
-    x.include.zero = FALSE, 
-    x.left.extra.margin = 0.05, 
-    x.right.extra.margin = 0.05, 
-    x.text.angle = 0, 
-    y.lim = NULL, 
-    y.lab = NULL, 
-    y.log = "no", 
-    y.tick.nb = NULL, 
-    y.second.tick.nb = NULL, 
-    y.include.zero = FALSE, 
-    y.top.extra.margin = 0.05, 
-    y.bottom.extra.margin = 0.05, 
-    y.text.angle = 0, 
-    raster = FALSE, 
-    raster.ratio = 1, 
-    raster.threshold = NULL, 
-    text.size = 12, 
-    title = "", 
-    title.text.size = 12, 
-    legend.show = TRUE, 
-    legend.width = 0.5, 
-    legend.name = NULL, 
-    article = TRUE, 
-    grid = FALSE, 
-    add = NULL, 
-    return = FALSE, 
-    return.ggplot = FALSE,
-    return.gtable = TRUE,
-    plot = TRUE, 
-    warn.print = FALSE, 
-    lib.path = NULL
-){
-    # AIM
-    # Plot ggplot2 scatterplot with the possibility to overlay dots from up to 3 different data frames (-> three different legends) and lines from up to 3 different data frames (-> three different legends) -> up to 6 overlays totally
-    # For ggplot2 specifications, see: https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
-    # WARNINGS
-    # Rows containing NA in data1[, c(x, y, categ)] will be removed before processing, with a warning (see below)
-    # Size arguments (dot.size, dot.border.size, line.size, text.size and title.text.size) are in mm. See Hadley comment in https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size. See also http://sape.inf.usi.ch/quick-reference/ggplot2/size). Unit object are not accepted, but conversion can be used (e.g., grid::convertUnit(grid::unit(0.2, "inches"), "mm", valueOnly = TRUE))
-    # ARGUMENTS
-    # data1: a dataframe compatible with ggplot2, or a list of data frames. Order matters for the order of the legend and for the layer staking (starting from below to top)
-    # x: single character string of the data1 column name for x-axis coordinates. If data1 is a list, then x must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Write NULL for each "geom_hline" in geom argument
-    # y: single character string of the data1 column name for y-axis coordinates. If data1 is a list, then y must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Write NULL for each "geom_vline" in geom argument
-    # categ: either NULL or a single character string or a list of single character strings, indicating the data1 column names to use for categories which creates legend display
-    # If categ == NULL, no categories -> no legend displayed
-    # If data1 is a data frame, categ must be a single character string of the data1 column name for categories
-    # If data1 is a list, then categ must be a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL (no legend display for these compartments), and other not
-    # categ.class.order: either (1) NULL or (2) a vector of character strings or (3) a list of these vectors, setting the order of the classes of categ in the legend display
-    # If categ.class.order is NULL, classes are represented according to the alphabetical order
-    # If data1 is a data frame, categ.class.order must be a vector of character strings specifying the different classes in the categ column name of data1
-    # If data1 is a list, then categ.class.order must be a list of vector of character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL (alphabetical order for these compartments), and other not
-    # color: either (1) NULL, or (2) a vector of character strings or integers, or (3) a list of vectors of character strings or integers
-    # If color is NULL, default colors of ggplot2
-    # If data1 is a data frame, color argument can be either:
-    # (1) a single color string. All the dots of the corresponding data1 will have this color, whatever the categ value (NULL or not)
-    # (2) if categ is non-null, a vector of string colors, one for each class of categ. Each color will be associated according to the categ.class.order argument if specified, or to the alphabetical order of categ classes otherwise
-    # (3) if categ is non-null, a vector or factor of string colors, like if it was one of the column of data1 data frame. WARNING: a single color per class of categ and a single class of categ per color must be respected
-    # Positive integers are also accepted instead of character strings, as long as above rules about length are respected. Integers will be processed by fun_gg_palette() using the max integer value among all the integers in color (see fun_gg_palette())
-    # If data1 is a list, then color argument must be either: 
-    # (1) a list of character strings or integers, of same size as data1, with compartment 1 related to compartment 1 of data1, etc.
-    # (2) a single character string or a single integer
-    # With a list (first possibility), the rules described for when data1 is a data frame apply to each compartment of the list. Some of the compartments can be NULL. In that case, a different grey color will be used for each NULL compartment. With a single value (second possibility), the same color will be used for all the dots and lines, whatever the data1 list
-    # geom: single character string of the kind of plot, or a list of single character strings
-    # Either:
-    # "geom_point" (scatterplot)
-    # "geom_line" (coordinates plotted then line connection, from the lowest to highest x coordinates first and from the lowest to highest y coordinates thenafter)
-    # "geom_path" (coordinates plotted then line connection respecting the row order in data1)
-    # "geom_step" coordinates plotted then line connection respecting the row order in data1 but drawn in steps). See the geom.step.dir argument
-    # "geom_hline" (horizontal line, no x value provided)
-    # "geom_vline" (vertical line, no y value provided)
-    # "geom_stick" (dots as vertical bars)
-    # If data1 is a list, then geom must be either:
-    # (1) a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc.
-    # (2) a single character string. In that case the same kind of plot will apply for the different compartments of the data1 list
-    # WARNING concerning "geom_hline" or "geom_vline":
-    # (1) x or y argument must be NULL, respectively
-    # (2) x.lim or y.lim argument must NOT be NULL, respectively, if only these kind of lines are drawn (if other geom present, then x.lim = NULL and y.lim = NULL will generate x.lim and y.lim defined by these other geom, which is not possible with "geom_hline" or "geom_vline" alone)
-    # (3) the function will draw n lines for n values in the x argument column name of the data1 data frame. If several colors required, the categ argument must be specified and the corresponding categ column name must exist in the data1 data frame with a different class name for each row
-    # geom.step.dir: single character string indicating the direction when using "geom_step" of the geom argument, or a list of single character strings
-    # Either:
-    # "vh" (vertical then horizontal)
-    # "hv" (horizontal then vertical)
-    # "mid" (step half-way between adjacent x-values)
-    # See https://ggplot2.tidyverse.org/reference/geom_path.html
-    # If data1 is a list, then geom.step.dir must be either:
-    # (1) a list of single character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. The value in compartments related to other geom values than "geom_step" will be ignored
-    # (2) a single character string, which will be used for all the "geom_step" values of the geom argument, whatever the data1 list
-    # geom.stick.base: either (1) NULL or (2) a single numeric value or (3) a list of single numeric values, setting the base of the sticks when using "geom_stick" of the geom argument
-    # If geom.stick.base is NULL, the bottom limit of the y-axis is taken as the base
-    # If data1 is a list, then geom.stick.base must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the values in compartments related to other geom values than "geom_stick" will be ignored. With a single value (latter possibility), the same base will be used for all the sticks, whatever the data1 list
-    # Warning: the y-axis limits are not modified by the value of geom.stick.base, meaning that this value can be outside of the range of y.lim. Add the value of geom.stick.base also in the y.lim argument if required
-    # Warning: if geom.stick.base is NULL, the bottom limit of the y-axis is taken as the base. Thus, be careful with inverted y-axis
-    # alpha: single numeric value (from 0 to 1) of transparency. If data1 is a list, then alpha must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. In that case the same transparency will apply for the different compartments of the data1 list
-    # dot.size: single numeric value of dot shape radius? in mm. If data1 is a list, then dot.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.size will be used for all the dots, whatever the data1 list
-    # dot.shape: value indicating the shape of the dots (see https://ggplot2.tidyverse.org/articles/ggplot2-specs.html) If data1 is a list, then dot.shape must be either (1) a list of single shape values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single shape value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.shape will be used for all the dots, whatever the data1 list
-    # dot.border.size: single numeric value of border dot width in mm. Write zero for no dot border. If data1 is a list, then dot.border.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to lines will be ignored. With a single value (latter possibility), the same dot.border.size will be used for all the dots, whatever the data1 list
-    # dot.border.color: single character color string defining the color of the dot border (same border color for all the dots, whatever their categories). If dot.border.color == NULL, the border color will be the same as the dot color. A single integer is also accepted instead of a character string, that will be processed by fun_gg_palette()
-    # line.size: single numeric value of line width in mm. If data1 is a list, then line.size must be either (1) a list of single numeric values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single numeric value. With a list (former possibility), the value in compartments related to dots will be ignored. With a single value (latter possibility), the same line.size will be used for all the lines, whatever the data1 list
-    # line.type: value indicating the kind of lines (see https://ggplot2.tidyverse.org/articles/ggplot2-specs.html) If data1 is a list, then line.type must be either (1) a list of single line kind values, of same size as data1, with compartment 1 related to compartment 1 of data1, etc., or (2) a single line kind value. With a list (former possibility), the value in compartments related to dots will be ignored. With a single value (latter possibility), the same line.type will be used for all the lines, whatever the data1 list
-    # x.lim: 2 numeric values setting the x-axis range. Order of the 2 values matters (for inverted axis). If NULL, the range of the x column name of data1 will be used
-    # x.lab: a character string or expression for x-axis label. If NULL, will use the first value of x (x column name of the first data frame in data1). Warning message if the elements in x are different between data frames in data1
-    # x.log: either "no", "log2" (values in the x column name of the data1 data frame will be log2 transformed and x-axis will be log2 scaled) or "log10" (values in the x column name of the data1 data frame will be log10 transformed and x-axis will be log10 scaled)
-    # x.tick.nb: approximate number of desired values labeling the x-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if x.log is "no", then the number of labeling values is set by ggplot2. If NULL and if x.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the x.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for x.lim = c(9, 1200)). WARNING: if non-NULL and if x.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
-    # x.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if x.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$x.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
-    # x.include.zero: logical. Does x.lim range include 0? Ignored if x.log is "log2" or "log10"
-    # x.left.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to x.lim. If different from 0, add the range of the axis multiplied by x.left.extra.margin (e.g., abs(x.lim[2] - x.lim[1]) * x.left.extra.margin) to the left of x-axis
-    # x.right.extra.margin: idem as x.left.extra.margin but to the right of x-axis
-    # x.text.angle: integer value of the text angle for the x-axis labeling values, using the same rules as in ggplot2. Use positive value for clockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Use negative values for counterclockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
-    # y.lim: 2 numeric values setting the y-axis range. Order of the 2 values matters (for inverted axis). If NULL, the range of the y column name of data1 will be used
-    # y.lab: a character string or expression for y-axis label. If NULL, will use the first value of y (y column name of the first data frame in data1). Warning message if the elements in y are different between data frames in data1
-    # y.log: either "no", "log2" (values in the y column name of the data1 data frame will be log2 transformed and y-axis will be log2 scaled) or "log10" (values in the y column name of the data1 data frame will be log10 transformed and y-axis will be log10 scaled)
-    # y.tick.nb: approximate number of desired values labeling the y-axis (i.e., main ticks, see the n argument of the the cute::fun_scale() function). If NULL and if y.log is "no", then the number of labeling values is set by ggplot2. If NULL and if y.log is "log2" or "log10", then the number of labeling values corresponds to all the exposant integers in the y.lim range (e.g., 10^1, 10^2 and 10^3, meaning 3 main ticks for y.lim = c(9, 1200)). WARNING: if non-NULL and if y.log is "log2" or "log10", labeling can be difficult to read (e.g., ..., 10^2, 10^2.5, 10^3, ...)
-    # y.second.tick.nb: number of desired secondary ticks between main ticks. Ignored if y.log is other than "no" (log scale plotted). Use argument return = TRUE and see $plot$y.second.tick.values to have the values associated to secondary ticks. IF NULL, no secondary ticks
-    # y.include.zero: logical. Does y.lim range include 0? Ignored if y.log is "log2" or "log10"
-    # y.top.extra.margin: single proportion (between 0 and 1) indicating if extra margins must be added to y.lim. If different from 0, add the range of the axis multiplied by y.top.extra.margin (e.g., abs(y.lim[2] - y.lim[1]) * y.top.extra.margin) to the top of y-axis
-    # y.bottom.extra.margin: idem as y.top.extra.margin but to the bottom of y-axis
-    # y.text.angle: integer value of the text angle for the y-axis labeling values, using the same rules as in ggplot2. Use positive value for clockwise rotation: 0 for horizontal, 90 for vertical, 180 for upside down etc. Use negative values for counterclockwise rotation: 0 for horizontal, -90 for vertical, -180 for upside down etc.
-    # raster: logical. Dots in raster mode? If FALSE, dots from each "geom_point" from geom argument are plotted in vectorial mode (bigger pdf and long to display if lots of dots). If TRUE, dots from each "geom_point" from geom argument are plotted in matricial mode (smaller pdf and easy display if lots of dots, but it takes time to generate the layer). If TRUE, the raster.ratio argument is used to avoid an ellipsoid representation of the dots. If TRUE, solve the transparency problem with some GUI. Overriden by the non-NULL raster.threshold argument
-    # raster.ratio: single numeric value indicating the height / width ratio of the graphic device used (for instance provided by the $dim compartment in the output of the fun_open() function). The default value is 1 because by default R opens a square graphic device. But this argument has to be set when using other device dimensions. Ignored if raster == FALSE
-    # raster.threshold: positive integer value indicating the limit of the dot number above which "geom_point" layers from the geom argument switch from vectorial mode to matricial mode (see the raster argument). If any layer is matricial, then the raster.ratio argument is used to avoid an ellipsoid representation of the dots. If non-NULL, it overrides the raster argument
-    # text.size: numeric value of the font size of the (1) axis numbers and axis legends and (2) texts in the graphic legend (in mm)
-    # title: character string of the graph title
-    # title.text.size: numeric value of the title font size in mm
-    # legend.show: logical. Show legend? Not considered if categ argument is NULL, because this already generate no legend, excepted if legend.width argument is non-NULL. In that specific case (categ is NULL, legend.show is TRUE and legend.width is non-NULL), an empty legend space is created. This can be useful when desiring graphs of exactly the same width, whatever they have legends or not
-    # legend.width: single proportion (between 0 and 1) indicating the relative width of the legend sector (on the right of the plot) relative to the width of the plot. Value 1 means that the window device width is split in 2, half for the plot and half for the legend. Value 0 means no room for the legend, which will overlay the plot region. Write NULL to inactivate the legend sector. In such case, ggplot2 will manage the room required for the legend display, meaning that the width of the plotting region can vary between graphs, depending on the text in the legend
-    # legend.name: character string of the legend title. If legend.name is NULL and categ argument is not NULL, then legend.name <- categ. If data1 is a list, then legend.name must be a list of character strings, of same size as data1, with compartment 1 related to compartment 1 of data1, etc. Some of the list compartments can be NULL, and other not
-    # article: logical. If TRUE, use an article theme (article like). If FALSE, use a classic related ggplot theme. Use the add argument (e.g., add = "+ggplot2::theme_classic()" for the exact classic ggplot theme
-    # grid: logical. Draw lines in the background to better read the box values? Not considered if article == FALSE (grid systematically present)
-    # add: character string allowing to add more ggplot2 features (dots, lines, themes, facet, etc.). Ignored if NULL
-    # WARNING: (1) the string must start with "+", (2) the string must finish with ")" and (3) each function must be preceded by "ggplot2::". Example: "+ ggplot2::coord_flip() + ggplot2::theme_bw()"
-    # If the character string contains the "ggplot2::theme" string, then the article argument of fun_gg_scatter() (see above) is ignored with a warning. In addition, some arguments can be overwritten, like x.angle (check all the arguments)
-    # Handle the add argument with caution since added functions can create conflicts with the preexisting internal ggplot2 functions
-    # WARNING: the call of objects inside the quotes of add can lead to an error if the name of these objects are some of the fun_gg_scatter() arguments. Indeed, the function will use the internal argument instead of the global environment object. Example article <- "a" in the working environment and add = '+ ggplot2::ggtitle(article)'. The risk here is to have TRUE as title. To solve this, use add = '+ ggplot2::ggtitle(get("article", envir = .GlobalEnv))'
-    # return: logical. Return the graph parameters?
-    # return.ggplot: logical. Return the ggplot object in the output list? Ignored if return argument is FALSE. WARNING: always assign the fun_gg_scatter() function (e.g., a <- fun_gg_scatter()) if return.ggplot argument is TRUE, otherwise, double plotting is performed. See $ggplot in the RETURN section below for more details
-    # return.gtable: logical. Return the ggplot object as gtable of grobs in the output list? Ignored if plot argument is FALSE. Indeed, the graph must be plotted to get the grobs dispositions. See $gtable in the RETURN section below for more details
-    # plot: logical. Plot the graphic? If FALSE and return argument is TRUE, graphical parameters and associated warnings are provided without plotting
-    # warn.print: logical. Print warnings at the end of the execution? ? If FALSE, warning messages are never printed, but can still be recovered in the returned list. Some of the warning messages (those delivered by the internal ggplot2 functions) are not apparent when using the argument plot = FALSE
-    # lib.path: character string indicating the absolute path of the required packages (see below). if NULL, the function will use the R library default folders
-    # RETURN
-    # a scatter plot if plot argument is TRUE
-    # a list of the graph info if return argument is TRUE:
-    # $data: the initial data with graphic information added. WARNING: if the x.log or y.log argument is not "no", x or y argument column of the data1 data frame are log2 or log10 converted in $data, respectively. Use 2^values or 10^$values to recover the initial values
-    # $removed.row.nb: a list of the removed rows numbers in data frames (because of NA). NULL if no row removed
-    # $removed.rows: a list of the removed rows in data frames (because of NA). NULL if no row removed
-    # $plot: the graphic box and dot coordinates
-    # $dots: dot coordinates
-    # y.second.tick.positions: coordinates of secondary ticks (only if y.second.tick.nb argument is non-null or if y.log argument is different from "no")
-    # y.second.tick.values: values of secondary ticks. NULL except if y.second.tick.nb argument is non-null or if y.log argument is different from "no")
-    # $panel: the variable names used for the panels (NULL if no panels). WARNING: NA can be present according to ggplot2 upgrade to v3.3.0
-    # $axes: the x-axis and y-axis info
-    # $warn: the warning messages. Use cat() for proper display. NULL if no warning. WARNING: warning messages delivered by the internal ggplot2 functions are not apparent when using the argument plot = FALSE
-    # $ggplot: ggplot object that can be used for reprint (use print($ggplot) or update (use $ggplot + ggplot2::...). NULL if return.ggplot argument is FALSE. Of note, a non-null $ggplot in the output list is sometimes annoying as the manipulation of this list prints the plot
-    # $gtable: gtable object that can be used for reprint (use gridExtra::grid.arrange(...$ggplot) or with additionnal grobs (see the grob decomposition in the examples). NULL if return.ggplot argument is FALSE. Contrary to $ggplot, a non-NULL $gtable in the output list is not annoying as the manipulation of this list does not print the plot
-    # REQUIRED PACKAGES
-    # ggplot2
-    # gridExtra
-    # lemon (in case of use in the add argument)
-    # scales
-    # if raster plots are drawn (see the raster and raster.threshold arguments):
-    # Cairo
-    # grid
-    # REQUIRED FUNCTIONS FROM THE cute PACKAGE
-    # fun_gg_empty_graph()
-    # fun_gg_palette()
-    # fun_gg_point_rast()
-    # fun_pack()
-    # fun_check()
-    # fun_round()
-    # fun_scale()
-    # fun_inter_ticks()
-    # EXAMPLES
-    # set.seed(1) ; obs1 <- data.frame(Km = c(2, 1, 6, 5, 4, 7), Time = c(2, 1, 6, 5, 4, 7)^2, Car = c("TUUT", "TUUT", "TUUT", "WIIM", "WIIM", "WIIM"), Color1 = rep(c("coral", "lightblue"), each = 3), stringsAsFactors = TRUE) ; fun_gg_scatter(data1 = obs1, x = "Km", y = "Time")
-    # DEBUGGING
-    # set.seed(1) ; obs1 <- data.frame(km = rnorm(1000, 10, 3), time = rnorm(1000, 10, 3), group1 = rep(c("A1", "A2"), 500), stringsAsFactors = TRUE) ; obs2 <-data.frame(km = rnorm(1000, 15, 3), time = rnorm(1000, 15, 3), group2 = rep(c("G1", "G2"), 500), stringsAsFactors = TRUE) ; set.seed(NULL) ; obs1$km[2:3] <- NA ; data1 = list(L1 = obs1, L2 = obs2) ; x = list(L1 = "km", L2 = "km") ; y = list(L1 = "time", L2 = "time") ; categ = list(L1 = "group1", L2 = "group2") ; categ = NULL ; categ.class.order = NULL ; color = NULL ; geom = "geom_point" ; geom.step.dir = "hv" ; geom.stick.base = NULL ; alpha = 0.5 ; dot.size = 2 ; dot.shape = 21 ; dot.border.size = 0.5 ; dot.border.color = NULL ; line.size = 0.5 ; line.type = "solid" ; x.lim = NULL ; x.lab = NULL ; x.log = "no" ; x.tick.nb = NULL ; x.second.tick.nb = NULL ; x.include.zero = FALSE ; x.left.extra.margin = 0.05 ; x.right.extra.margin = 0.05 ; x.text.angle = 0 ; y.lim = NULL ; y.lab = NULL ; y.log = "no" ; y.tick.nb = NULL ; y.second.tick.nb = NULL ; y.include.zero = FALSE ; y.top.extra.margin = 0.05 ; y.bottom.extra.margin = 0.05 ; y.text.angle = 0 ; raster = FALSE ; raster.ratio = 1 ; raster.threshold = NULL ; text.size = 12 ; title = "" ; title.text.size = 12 ; legend.show = TRUE ; legend.width = 0.5 ; legend.name = NULL ; article = TRUE ; grid = FALSE ; add = NULL ; return = FALSE ; return.ggplot = FALSE ; return.gtable = TRUE ; plot = TRUE ; warn.print = FALSE ; lib.path = NULL
-    # function name
-    function.name <- paste0(as.list(match.call(expand.dots=FALSE))[[1]], "()")
-    arg.names <- names(formals(fun = sys.function(sys.parent(n = 2)))) # names of all the arguments
-    arg.user.setting <- as.list(match.call(expand.dots=FALSE))[-1] # list of the argument settings (excluding default values not provided by the user)
-    # end function name
-    # required function checking
-    req.function <- c(
-        "fun_check", 
-        "fun_gg_just", 
-        "fun_gg_empty_graph", 
-        "fun_gg_palette", 
-        "fun_gg_point_rast", 
-        "fun_round", 
-        "fun_pack", 
-        "fun_scale", 
-        "fun_inter_ticks"
-    )
-    tempo <- NULL
-    for(i1 in req.function){
-        if(length(find(i1, mode = "function"))== 0L){
-            tempo <- c(tempo, i1)
-        }
-    }
-    if( ! is.null(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nREQUIRED cute FUNCTION", ifelse(length(tempo) > 1, "S ARE", " IS"), " MISSING IN THE R ENVIRONMENT:\n", paste0(tempo, collapse = "()\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end required function checking
-    # reserved words to avoid bugs (used in this function)
-    reserved.words <- c("fake_x", "fake_y", "fake_categ")
-    # end reserved words to avoid bugs (used in this function)
-    # arg with no default values
-    mandat.args <- c(
-        "data1", 
-        "x", 
-        "y"
-    )
-    tempo <- eval(parse(text = paste0("missing(", paste0(mandat.args, collapse = ") | missing("), ")")))
-    if(any(tempo)){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nFOLLOWING ARGUMENT", ifelse(length(mandat.args) > 1, "S HAVE", "HAS"), " NO DEFAULT VALUE AND REQUIRE ONE:\n", paste0(mandat.args, collapse = "\n"))
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end arg with no default values
-    # argument primary checking
-    arg.check <- NULL #
-    text.check <- NULL #
-    checked.arg.names <- NULL # for function debbuging: used by r_debugging_tools
-    ee <- expression(arg.check <- c(arg.check, tempo$problem) , text.check <- c(text.check, tempo$text) , checked.arg.names <- c(checked.arg.names, tempo$object.name))
-    tempo1 <- fun_check(data = data1, class = "data.frame", na.contain = TRUE, fun.name = function.name)
-    tempo2 <- fun_check(data = data1, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OR A LIST OF DATA FRAMES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(x)){
-        tempo1 <- fun_check(data = x, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = x, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(y)){
-        tempo1 <- fun_check(data = y, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = y, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(categ)){
-        tempo1 <- fun_check(data = categ, class = "vector", mode = "character", length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = categ, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = categ, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(categ.class.order)){
-        if(is.null(categ)){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT IS NOT NULL, BUT categ IS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-        tempo1 <- fun_check(data = categ.class.order, class = "vector", mode = "character", fun.name = function.name)
-        tempo2 <- fun_check(data = categ.class.order, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT MUST BE A VECTOR OF CHARACTER STRINGS OR A LIST OF VECTOR OF CHARACTER STRINGS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = categ.class.order, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(legend.name)){
-        tempo1 <- fun_check(data = legend.name, class = "vector", mode = "character", na.contain = TRUE, length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = legend.name, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = legend.name, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(color)){
-        tempo1 <- fun_check(data = color, class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-        tempo2 <- fun_check(data = color, class = "factor", na.contain = TRUE, fun.name = function.name)
-        tempo3 <- fun_check(data = color, class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)
-        tempo4 <- fun_check(data = color, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo4$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE & tempo3$problem == TRUE & tempo4$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT MUST BE A VECTOR (OF CHARACTER STRINGS OR INTEGERS) OR A FACTOR OR A LIST OF THESE POSSIBILITIES")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = color, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo1 <- fun_check(data = geom, class = "vector", mode = "character", na.contain = FALSE, length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = geom, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT MUST BE A SINGLE CHARACTER STRING OR A LIST OF CHARACTER STRINGS")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo1 <- fun_check(data = geom.step.dir, options = c("vh", "hv", "mid"), na.contain = FALSE, length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = geom.step.dir, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT MUST BE A SINGLE CHARACTER STRING (\"vh\" OR \"hv\" OR \"mid\") OR A LIST OF THESE CHARACTER STRINGS")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(geom.stick.base)){
-        tempo1 <- fun_check(data = geom.stick.base, class = "vector", mode = "numeric", na.contain = FALSE, length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = color, class = "list", na.contain = TRUE, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = geom.stick.base, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo1 <- fun_check(data = alpha, prop = TRUE, length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = alpha, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT MUST BE A SINGLE NUMERIC VALUE BETWEEN 0 AND 1 OR A LIST OF SUCH VALUES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo1 <- fun_check(data = dot.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
-    tempo2 <- fun_check(data = dot.size, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo1 <- fun_check(data = dot.shape, class = "vector", length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = dot.shape, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT MUST BE A SINGLE SHAPE VALUE OR A LIST OF SINGLE SHAPE VALUES (SEE https://ggplot2.tidyverse.org/articles/ggplot2-specs.html)")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo1 <- fun_check(data = dot.border.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
-    tempo2 <- fun_check(data = dot.border.size, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(dot.border.color)){
-        tempo1 <- fun_check(data = dot.border.color, class = "vector", mode = "character", length = 1, fun.name = function.name)
-        tempo2 <- fun_check(data = dot.border.color, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, fun.name = function.name)
-        checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-        if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-            # integer colors -> gg_palette
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color MUST BE A SINGLE CHARACTER STRING OF COLOR OR A SINGLE INTEGER VALUE")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = dot.border.color, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo1 <- fun_check(data = line.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name)
-    tempo2 <- fun_check(data = line.size, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo2$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT MUST BE A SINGLE NUMERIC VALUE OR A LIST OF SINGLE NUMERIC VALUES")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    tempo1 <- fun_check(data = line.type, class = "vector", typeof = "integer", double.as.integer.allowed = FALSE, length = 1, fun.name = function.name)
-    tempo2 <- fun_check(data = line.type, class = "vector", mode = "character", length = 1, fun.name = function.name)
-    tempo3 <- fun_check(data = line.type, class = "list", na.contain = TRUE, fun.name = function.name)
-    checked.arg.names <- c(checked.arg.names, tempo3$object.name)
-    if(tempo1$problem == TRUE & tempo2$problem == TRUE & tempo3$problem == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT MUST BE A SINGLE LINE KIND VALUE OR A LIST OF SINGLE LINE KIND VALUES (SEE https://ggplot2.tidyverse.org/articles/ggplot2-specs.html)")
-        text.check <- c(text.check, tempo.cat)
-        arg.check <- c(arg.check, TRUE)
-    }
-    if( ! is.null(x.lim)){
-        tempo <- fun_check(data = x.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & any(x.lim %in% c(Inf, -Inf))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x.lim, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(x.lab)){
-        if(all(class(x.lab) %in% "expression")){ # to deal with math symbols
-            tempo <- fun_check(data = x.lab, class = "expression", length = 1, fun.name = function.name) ; eval(ee)
-        }else{
-            tempo <- fun_check(data = x.lab, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x.lab, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = x.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(x.tick.nb)){
-        tempo <- fun_check(data = x.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & x.tick.nb < 0){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(x.second.tick.nb)){
-        tempo <- fun_check(data = x.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & x.second.tick.nb <= 0){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x.second.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = x.second.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = x.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.left.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.right.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = x.text.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(y.lim)){
-        tempo <- fun_check(data = y.lim, class = "vector", mode = "numeric", length = 2, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & any(y.lim %in% c(Inf, -Inf))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y.lim ARGUMENT CANNOT CONTAIN -Inf OR Inf VALUES")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.lim, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(y.lab)){
-        if(all(class(y.lab) %in% "expression")){ # to deal with math symbols
-            tempo <- fun_check(data = y.lab, class = "expression", length = 1, fun.name = function.name) ; eval(ee)
-        }else{
-            tempo <- fun_check(data = y.lab, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.lab, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = y.log, options = c("no", "log2", "log10"), length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(y.tick.nb)){
-        tempo <- fun_check(data = y.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & y.tick.nb < 0){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if( ! is.null(y.second.tick.nb)){
-        tempo <- fun_check(data = y.second.tick.nb, class = "vector", typeof = "integer", length = 1, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE & y.second.tick.nb <= 0){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y.second.tick.nb ARGUMENT MUST BE A NON-NULL POSITIVE INTEGER")
-            text.check <- c(text.check, tempo.cat)
-            arg.check <- c(arg.check, TRUE)
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = y.second.tick.nb, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = y.include.zero, class = "vector", mode = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.top.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.bottom.extra.margin, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = y.text.angle, class = "vector", typeof = "integer", double.as.integer.allowed = TRUE, length = 1, neg.values = TRUE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = raster, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = raster.ratio, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    if( ! is.null(raster.threshold)){
-        tempo <- fun_check(data = raster.threshold, class = "vector", typeof = "integer", neg.values = FALSE, double.as.integer.allowed = TRUE, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = raster.threshold, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = title.text.size, class = "vector", mode = "numeric", length = 1, neg.values = FALSE, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = legend.show, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(legend.width)){
-        tempo <- fun_check(data = legend.width, prop = TRUE, length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = legend.width, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = article, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = grid, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(add)){
-        tempo <- fun_check(data = add, class = "vector", mode = "character", length = 1, fun.name = function.name) ; eval(ee)
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = add, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    tempo <- fun_check(data = return, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.ggplot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = return.gtable, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = plot, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    tempo <- fun_check(data = warn.print, class = "logical", length = 1, fun.name = function.name) ; eval(ee)
-    if( ! is.null(lib.path)){
-        tempo <- fun_check(data = lib.path, class = "vector", mode = "character", fun.name = function.name) ; eval(ee)
-        if(tempo$problem == FALSE){
-            if( ! all(dir.exists(lib.path))){ # separation to avoid the problem of tempo$problem == FALSE and lib.path == NA
-                tempo.cat <- paste0("ERROR IN ", function.name, ": DIRECTORY PATH INDICATED IN THE lib.path ARGUMENT DOES NOT EXISTS:\n", paste(lib.path, collapse = "\n"))
-                text.check <- c(text.check, tempo.cat)
-                arg.check <- c(arg.check, TRUE)
-            }
-        }
-    }else{
-        # no fun_check test here, it is just for checked.arg.names
-        tempo <- fun_check(data = lib.path, class = "vector")
-        checked.arg.names <- c(checked.arg.names, tempo$object.name)
-    }
-    if(any(arg.check) == TRUE){
-        stop(paste0("\n\n================\n\n", paste(text.check[arg.check], collapse = "\n"), "\n\n================\n\n"), call. = FALSE) #
-    }
-    # source("C:/Users/Gael/Documents/Git_versions_to_use/debugging_tools_for_r_dev-v1.7/r_debugging_tools-v1.7.R") ; eval(parse(text = str_basic_arg_check_dev)) ; eval(parse(text = str_arg_check_with_fun_check_dev)) # activate this line and use the function (with no arguments left as NULL) to check arguments status and if they have been checked using fun_check()
-    # end argument primary checking
-    
-    
-    # second round of checking and data preparation
-    # management of NA arguments
-    tempo.arg <- names(arg.user.setting) # values provided by the user
-    tempo.log <- suppressWarnings(sapply(lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.na), FUN = any)) & lapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = length)== 1L # no argument provided by the user can be just NA
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT JUST BE NA")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NA arguments
-    # management of NULL arguments
-    tempo.arg <-c(
-        "data1", 
-        # "x", # inactivated because of hline or vline
-        # "y", # inactivated because of hline or vline
-        "geom", 
-        "geom.step.dir", 
-        # "geom.stick.base", # inactivated because can be null
-        "alpha", 
-        "dot.size", 
-        "dot.shape", 
-        "dot.border.size", 
-        "line.size", 
-        "line.type", 
-        "x.log", 
-        "x.include.zero", 
-        "x.left.extra.margin", 
-        "x.right.extra.margin", 
-        "x.text.angle", 
-        "y.log", 
-        "y.include.zero", 
-        "y.top.extra.margin", 
-        "y.bottom.extra.margin", 
-        "y.text.angle", 
-        "raster", 
-        "raster.ratio", 
-        "text.size", 
-        "title", 
-        "title.text.size", 
-        "legend.show", 
-        # "legend.width", # inactivated because can be null
-        "article", 
-        "grid", 
-        "return", 
-        "return.ggplot", 
-        "return.gtable", 
-        "plot", 
-        "warn.print"
-    )
-    tempo.log <- sapply(lapply(tempo.arg, FUN = get, env = sys.nframe(), inherit = FALSE), FUN = is.null)
-    if(any(tempo.log) == TRUE){
-        tempo.cat <- paste0("ERROR IN ", function.name, ":\n", ifelse(sum(tempo.log, na.rm = TRUE) > 1, "THESE ARGUMENTS\n", "THIS ARGUMENT\n"), paste0(tempo.arg[tempo.log], collapse = "\n"),"\nCANNOT BE NULL")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n"), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }
-    # end management of NULL arguments
-    # code that protects set.seed() in the global environment
-    # end code that protects set.seed() in the global environment
-    # warning initiation
-    ini.warning.length <- options()$warning.length
-    options(warning.length = 8170)
-    warn <- NULL
-    warn.count <- 0
-    # end warning initiation
-    # other checkings
-    # check list lengths (and names of data1 compartments if present)
-    list.color <- NULL
-    list.geom <- NULL
-    list.geom.step.dir <- NULL
-    list.geom.stick.base <- NULL
-    list.alpha <- NULL
-    list.dot.size <- NULL
-    list.dot.shape <- NULL
-    list.dot.border.size <- NULL
-    list.dot.border.color <- NULL
-    list.line.size <- NULL
-    list.line.type <- NULL
-    if(all(class(data1) == "list")){
-        if(length(data1) > 6){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A LIST OF 6 DATA FRAMES MAXIMUM (6 OVERLAYS MAX)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        if(is.null(names(data1))){
-            names(data1) <- paste0("L", 1:length(data1))
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NULL NAME COMPARTMENT OF data1 LIST -> NAMES RESPECTIVELY ATTRIBUTED TO EACH COMPARTMENT:\n", paste(names(data1), collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        if( ! is.null(x)){
-            if( ! (all(class(x) == "list") & length(data1) == length(x))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }else{
-            x <- vector("list", length(data1))
-        }
-        if( ! is.null(y)){
-            if( ! (all(class(y) == "list") & length(data1) == length(y))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }else{
-            y <- vector("list", length(data1))
-        }
-        if( ! is.null(categ)){
-            if( ! (all(class(categ) == "list") & length(data1) == length(categ))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        if( ! is.null(categ.class.order)){
-            if( ! (all(class(categ.class.order) == "list") & length(data1) == length(categ.class.order))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        if( ! is.null(color)){
-            if( ! ((all(class(color) == "list") & length(data1) == length(color)) | ((all(mode(color) == "character") | all(mode(color) == "numeric")) & length(color)== 1L))){ # list of same length as data1 or single value
-                tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER STRING OR INTEGER")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if((all(mode(color) == "character") | all(mode(color) == "numeric")) & length(color)== 1L){ # convert the single value into a list of single value
-                list.color <- vector(mode = "list", length = length(data1))
-                list.color[] <- color
-            }
-        }
-        if( ! ((all(class(geom) == "list") & length(data1) == length(geom)) | (all(mode(geom) == "character") & length(geom)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(geom) == "character") & length(geom)== 1L){ # convert the single value into a list of single value
-            list.geom <- vector(mode = "list", length = length(data1))
-            list.geom[] <- geom
-        }
-        if( ! ((all(class(geom.step.dir) == "list") & length(data1) == length(geom.step.dir)) | (all(mode(geom.step.dir) == "character") & length(geom.step.dir)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(geom.step.dir) == "character") & length(geom.step.dir)== 1L){ # convert the single value into a list of single value
-            list.geom.step.dir <- vector(mode = "list", length = length(data1))
-            list.geom.step.dir[] <- geom.step.dir
-        }
-        if( ! is.null(geom.stick.base)){
-            if( ! ((all(class(geom.stick.base) == "list") & length(data1) == length(geom.stick.base)) | (all(mode(geom.stick.base) == "numeric") & length(geom.stick.base)== 1L))){ # list of same length as data1 or single value
-                tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if(all(mode(geom.stick.base) == "numeric") & length(geom.stick.base)== 1L){ # convert the single value into a list of single value
-                list.geom.stick.base <- vector(mode = "list", length = length(data1))
-                list.geom.stick.base[] <- geom.stick.base
-            }
-        }
-        if( ! ((all(class(alpha) == "list") & length(data1) == length(alpha)) | (all(mode(alpha) == "numeric") & length(alpha)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(alpha) == "numeric") & length(alpha)== 1L){ # convert the single value into a list of single value
-            list.alpha <- vector(mode = "list", length = length(data1))
-            list.alpha[] <- alpha
-        }
-        if( ! ((all(class(dot.size) == "list") & length(data1) == length(dot.size)) | (all(mode(dot.size) == "numeric") & length(dot.size)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(dot.size) == "numeric") & length(dot.size)== 1L){ # convert the single value into a list of single value
-            list.dot.size <- vector(mode = "list", length = length(data1))
-            list.dot.size[] <- dot.size
-        }
-        if( ! ((all(class(dot.shape) == "list") & length(data1) == length(dot.shape)) | (all(mode(dot.shape) != "list") & length(dot.shape)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE SHAPE VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(dot.shape) != "list") & length(dot.shape)== 1L){ # convert the single value into a list of single value
-            list.dot.shape <- vector(mode = "list", length = length(data1))
-            list.dot.shape[] <- dot.shape
-        }
-        if( ! ((all(class(dot.border.size) == "list") & length(data1) == length(dot.border.size)) | (all(mode(dot.border.size) == "numeric") & length(dot.border.size)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(dot.border.size) == "numeric") & length(dot.border.size)== 1L){ # convert the single value into a list of single value
-            list.dot.border.size <- vector(mode = "list", length = length(data1))
-            list.dot.border.size[] <- dot.border.size
-        }
-        if( ! is.null(dot.border.color)){
-            if( ! ((all(class(dot.border.color) == "list") & length(data1) == length(dot.border.color)) | ((all(mode(dot.border.color) == "character") | all(mode(dot.border.color) == "numeric")) & length(dot.border.color)== 1L))){ # list of same length as data1 or single value
-                tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE CHARACTER STRING OR INTEGER")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if((all(mode(dot.border.color) == "character") | all(mode(dot.border.color) == "numeric")) & length(dot.border.color)== 1L){ # convert the single value into a list of single value
-                list.dot.border.color <- vector(mode = "list", length = length(data1))
-                list.dot.border.color[] <- dot.border.color
-            }
-        }
-        if( ! ((all(class(line.size) == "list") & length(data1) == length(line.size)) | (all(mode(line.size) == "numeric") & length(line.size)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE NUMERIC VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(line.size) == "numeric") & length(line.size)== 1L){ # convert the single value into a list of single value
-            list.line.size <- vector(mode = "list", length = length(data1))
-            list.line.size[] <- line.size
-        }
-        if( ! ((all(class(line.type) == "list") & length(data1) == length(line.type)) | (all(mode(line.type) != "list") & length(line.type)== 1L))){ # list of same length as data1 or single value
-            tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST, OR A SINGLE LINE KIND VALUE")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(all(mode(line.type) != "list") & length(line.type)== 1L){ # convert the single value into a list of single value
-            list.line.type <- vector(mode = "list", length = length(data1))
-            list.line.type[] <- line.type
-        }
-        if( ! is.null(legend.name)){
-            if( ! (all(class(legend.name) == "list") & length(data1) == length(legend.name))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT MUST BE A LIST OF SAME LENGTH AS data1 IF data1 IS A LIST")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-    }
-    # end check list lengths (and names of data1 compartments if present)
-    # conversion into lists
-    if(all(is.data.frame(data1))){
-        data1 <- list(L1 = data1)
-        if(all(class(x) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": x ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            x <- list(L1 = x)
-        }
-        if(all(class(y) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": y ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            y <- list(L1 = y)
-        }
-        if( ! is.null(categ)){
-            if(all(class(categ) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": categ ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                categ <- list(L1 = categ)
-            }
-        }
-        if( ! is.null(categ.class.order)){
-            if(all(class(categ.class.order) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": categ.class.order ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                categ.class.order <- list(L1 = categ.class.order)
-            }
-        }
-        if( ! is.null(color)){
-            if(all(class(color) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": color ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                color <- list(L1 = color)
-            }
-        }
-        if(all(class(geom) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            geom <- list(L1 = geom)
-        }
-        if(all(class(geom.step.dir) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": geom.step.dir ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            geom.step.dir <- list(L1 = geom.step.dir)
-        }
-        if( ! is.null(geom.stick.base)){
-            if(all(class(geom.stick.base) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": geom.stick.base ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                geom.stick.base <- list(L1 = geom.stick.base)
-            }
-        }
-        if(all(class(alpha) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": alpha ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            alpha <- list(L1 = alpha)
-        }
-        if(all(class(dot.size) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            dot.size <- list(L1 = dot.size)
-        }
-        if(all(class(dot.shape) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.shape ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            dot.shape <- list(L1 = dot.shape)
-        }
-        if(all(class(dot.border.size) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            dot.border.size <- list(L1 = dot.border.size)
-        }
-        if( ! is.null(dot.border.color)){
-            if(all(class(dot.border.color) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": dot.border.color ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                dot.border.color <- list(L1 = dot.border.color)
-            }
-        }
-        if(all(class(line.size) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": line.size ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            line.size <- list(L1 = line.size)
-        }
-        if(all(class(line.type) == "list")){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": line.type ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            line.type <- list(L1 = line.type)
-        }
-        if( ! is.null(legend.name)){
-            if(all(class(legend.name) == "list")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": legend.name ARGUMENT CANNOT BE A LIST IF data1 IS A DATA FRAME")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                legend.name <- list(L1 = legend.name)
-            }
-        }
-    }else if( ! all(sapply(data1, FUN = "class") == "data.frame")){ # if not a data frame, data1 can only be a list, as tested above
-        tempo.cat <- paste0("ERROR IN ", function.name, ": data1 ARGUMENT MUST BE A DATA FRAME OR A LIST OF DATA FRAMES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    # single value converted into list now reattributed to the argument name
-    if( ! is.null(color)){
-        if( ! is.null(list.color)){
-            color <- list.color
-        }
-    }
-    if( ! is.null(list.geom)){
-        geom <- list.geom
-    }
-    if( ! is.null(list.geom.step.dir)){
-        geom.step.dir <- list.geom.step.dir
-    }
-    if( ! is.null(geom.stick.base)){
-        if( ! is.null(list.geom.stick.base)){
-            geom.stick.base <- list.geom.stick.base
-        }
-    }
-    if( ! is.null(list.alpha)){
-        alpha <- list.alpha
-    }
-    if( ! is.null(list.dot.size)){
-        dot.size <- list.dot.size
-    }
-    if( ! is.null(list.dot.shape)){
-        dot.shape <- list.dot.shape
-    }
-    if( ! is.null(list.dot.border.size)){
-        dot.border.size <- list.dot.border.size
-    }
-    if( ! is.null(dot.border.color)){
-        if( ! is.null(list.dot.border.color)){
-            dot.border.color <- list.dot.border.color
-        }
-    }
-    if( ! is.null(list.line.size)){
-        line.size <- list.line.size
-    }
-    if( ! is.null(list.line.type)){
-        line.type <- list.line.type
-    }
-    # end single value converted into list now reattributed to the argument name
-    # data, x, y, geom, alpha, dot.size, shape, dot.border.size, line.size, line.type, legend.name are list now
-    # if non-null, categ, categ.class.order, legend.name, color, dot.border.color are list now
-    # end conversion into lists
-    # verif of add
-    if( ! is.null(add)){
-        if( ! grepl(pattern = "^\\s*\\+", add)){ # check that the add string start by +
-            tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST START WITH \"+\": ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            
-        }else if( ! grepl(pattern = "(ggplot2|lemon)\\s*::", add)){ #
-            tempo.cat <- paste0("ERROR IN ", function.name, ": FOR EASIER FUNCTION DETECTION, add ARGUMENT MUST CONTAIN \"ggplot2::\" OR \"lemon::\" IN FRONT OF EACH GGPLOT2 FUNCTION: ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if( ! grepl(pattern = ")\\s*$", add)){ # check that the add string finished by )
-            tempo.cat <- paste0("ERROR IN ", function.name, ": add ARGUMENT MUST FINISH BY \")\": ", paste(unique(add), collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    # end verif of add
-    # management of add containing facet
-    facet.categ <- NULL
-    if( ! is.null(add)){
-        facet.check <- TRUE
-        tempo <- unlist(strsplit(x = add, split = "\\s*\\+\\s*(ggplot2|lemon)\\s*::\\s*")) #
-        tempo <- sub(x = tempo, pattern = "^facet_wrap", replacement = "ggplot2::facet_wrap")
-        tempo <- sub(x = tempo, pattern = "^facet_grid", replacement = "ggplot2::facet_grid")
-        tempo <- sub(x = tempo, pattern = "^facet_rep", replacement = "lemon::facet_rep")
-        if(length(data1) > 1 & (any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")) | grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid"))){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nfacet PANELS CANNOT BE USED IF MORE THAN ONE DATA FRAME IN THE data1 ARGUMENT\nPLEASE REWRITE THE add STRING AND RERUN")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            if(any(grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap"))){
-                tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_wrap|lemon::facet_rep_wrap")])))
-                facet.categ <- list(names(tempo1$params$facets)) # list of length 1
-                tempo.text <- "facet_wrap OR facet_rep_wrap"
-                facet.check <- FALSE
-            }else if(grepl(x = add, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")){
-                tempo1 <- suppressWarnings(eval(parse(text = tempo[grepl(x = tempo, pattern = "ggplot2::facet_grid|lemon::facet_rep_grid")])))
-                facet.categ <- list(c(names(tempo1$params$rows), names(tempo1$params$cols))) # list of length 1
-                tempo.text <- "facet_grid OR facet_rep_grid"
-                facet.check <- FALSE
-            }
-            if(facet.check == FALSE & ! all(facet.categ %in% names(data1[[1]]))){ # WARNING: all(facet.categ %in% names(data1)) is TRUE when facet.categ is NULL
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF \"", tempo.text, "\" STRING IN THE add ARGUMENT BUT PROBLEM OF VARIABLE DETECTION (COLUMN NAMES OF data1)\nTHE DETECTED VARIABLES ARE:\n", paste(facet.categ, collapse = " "), "\nTHE data1 COLUMN NAMES ARE:\n", paste(names(data1[[1]]), collapse = " "), "\nPLEASE REWRITE THE add STRING AND RERUN")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-    }
-    # if facet.categ is not NULL, it is a list of length 1 now
-    # end management of add containing facet
-    # legend name filling
-    if(is.null(legend.name) & ! is.null(categ)){
-        legend.name <- categ
-    }else if(is.null(legend.name) & is.null(categ)){
-        legend.name <- vector("list", length(data1)) # null list
-    }
-    # legend.name not NULL anymore (list)
-    # end legend name filling
-    # ini categ for legend display
-    fin.lg.disp <- vector("list", 6) # will be used at the end to display or not legends
-    fin.lg.disp[] <- FALSE
-    legend.disp <- vector("list", length(data1))
-    if(is.null(categ) | legend.show == FALSE){
-        legend.disp[] <- FALSE
-    }else{
-        for(i2 in 1:length(data1)){
-            if(is.null(categ[[i2]])){
-                legend.disp[[i2]] <- FALSE
-            }else{
-                legend.disp[[i2]] <- TRUE
-            }
-        }
-    }
-    # end ini categ for legend display
-    # integer colors into gg_palette
-    tempo.check.color <- NULL
-    for(i1 in 1:length(data1)){
-        if(any(is.na(color[[i1]]))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), ": color ARGUMENT CANNOT CONTAIN NA")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        tempo.check.color <- c(tempo.check.color, fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "integer", double.as.integer.allowed = TRUE, na.contain = TRUE, fun.name = function.name)$problem)
-    }
-    tempo.check.color <- ! tempo.check.color # invert TRUE and FALSE because if integer, then problem = FALSE
-    if(any(tempo.check.color == TRUE)){ # convert integers into colors
-        tempo.integer <- unlist(color[tempo.check.color])
-        tempo.color <- fun_gg_palette(max(tempo.integer, na.rm = TRUE))
-        for(i1 in 1:length(data1)){
-            if(tempo.check.color[i1] == TRUE){
-                color[[i1]] <-tempo.color[color[[i1]]]
-            }
-        }
-    }
-    # end integer colors into gg_palette
-    # loop (checking inside list compartment)
-    compart.null.color <- 0 # will be used to attribute a color when color is non-null but a compartment of color is NULL
-    data1.ini <- data1 # to report NA removal
-    removed.row.nb <- vector("list", length = length(data1)) # to report NA removal. Contains NULL
-    removed.rows <- vector("list", length = length(data1)) # to report NA removal. Contains NULL
-    for(i1 in 1:length(data1)){
-        tempo <- fun_check(data = data1[[i1]], data.name = ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "data.frame", na.contain = TRUE, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        # reserved word checking
-        if(any(names(data1[[i1]]) %in% reserved.words)){ # I do not use fun_name_change() because cannot control y before creating "fake_y". But ok because reserved are not that common
-            tempo.cat <- paste0("ERROR IN ", function.name, ": COLUMN NAMES OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " ARGUMENT CANNOT BE ONE OF THESE WORDS\n", paste(reserved.words, collapse = " "), "\nTHESE ARE RESERVED FOR THE ", function.name, " FUNCTION")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        if( ! (is.null(add))){
-            if(any(sapply(X = reserved.words, FUN = grepl, x = add))){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nDETECTION OF COLUMN NAMES OF data1 IN THE add ARGUMENT STRING, THAT CORRESPOND TO RESERVED STRINGS FOR ", function.name, "\nFOLLOWING COLUMN NAMES HAVE TO BE CHANGED:\n", paste(arg.names[sapply(X = reserved.words, FUN = grepl, x = add)], collapse = "\n"), "\nFOR INFORMATION, THE RESERVED WORDS ARE:\n", paste(reserved.words, collapse = "\n"))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if(any(sapply(X = arg.names, FUN = grepl, x = add))){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") NAMES OF ", function.name, " ARGUMENTS DETECTED IN THE add STRING:\n", paste(arg.names[sapply(X = arg.names, FUN = grepl, x = add)], collapse = "\n"), "\nRISK OF WRONG OBJECT USAGE INSIDE ", function.name)
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        # end reserved word checking
-        # check of geom now because required for y argument
-        tempo <- fun_check(data = geom[[i1]], data.name = ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), options = c("geom_point", "geom_line", "geom_path", "geom_step", "geom_hline", "geom_vline", "geom_stick"), length = 1, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        if(geom[[i1]] == "geom_step" & is.null(geom.step.dir[[i1]])){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(geom.step.dir)== 1L, "geom.step.dir", paste0("ELEMENT ", i1, " OF geom.step.dir ARGUMENT")), ": geom.step.dir ARGUMENT CANNOT BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("ELEMENT ", i1, " OF geom")), " ARGUMENT IS \"geom_step\"\nHERE geom.step.dir ARGUMENT IS: ", paste(geom.step.dir[[i1]], collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(geom[[i1]] == "geom_step" & ! is.null(geom.step.dir[[i1]])){
-            tempo <- fun_check(data = geom.step.dir[[i1]], data.name = ifelse(length(geom.step.dir)== 1L, "geom.step.dir", paste0("geom.step.dir NUMBER ", i1)), options = c("vh", "hv", "mid"), length = 1, fun.name = function.name)
-            if(tempo$problem == TRUE){
-                stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        if( ! (is.null(geom.stick.base))){
-            if(geom[[i1]] == "geom_stick" & ! is.null(geom.stick.base[[i1]])){
-                tempo <- fun_check(data = geom.stick.base[[i1]], data.name = ifelse(length(geom.stick.base)== 1L, "geom.stick.base", paste0("geom.stick.base NUMBER ", i1)), mode = "numeric", length = 1, na.contain = FALSE, fun.name = function.name)
-                if(tempo$problem == TRUE){
-                    stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }
-            }
-        }
-        # end check of geom now because required for y argument
-        if(is.null(x[[i1]])){
-            if(all(geom[[i1]] != "geom_hline")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": x ARGUMENT CANNOT BE NULL EXCEPT IF ", ifelse(length(geom)== 1L, "x", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_hline\"\nHERE geom ARGUMENT IS: ", paste(geom[[i1]], collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                x[[i1]] <- "fake_x"
-                data1[[i1]] <- cbind(data1[[i1]], fake_x = NA, stringsAsFactors = TRUE)
-                data1[[i1]][, "fake_x"] <- as.numeric(data1[[i1]][, "fake_x"])
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT ASSOCIATED TO ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT ", geom[[i1]], " -> FAKE COLUMN ADDED TO DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", NAMED \"fake_x\" FOR FINAL DRAWING")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }else{
-            if(all(geom[[i1]] == "geom_hline")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": x ARGUMENT MUST BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_hline\"")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-            tempo <- fun_check(data = x[[i1]], data.name = ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), class = "vector", mode = "character", length = 1, fun.name = function.name)
-            if(tempo$problem == TRUE){
-                stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        if(is.null(y[[i1]])){
-            if(all(geom[[i1]] != "geom_vline")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": y ARGUMENT CANNOT BE NULL EXCEPT IF ", ifelse(length(geom)== 1L, "y", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_vline\"\nHERE geom ARGUMENT IS: ", paste(geom[[i1]], collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                y[[i1]] <- "fake_y"
-                data1[[i1]] <- cbind(data1[[i1]], fake_y = NA, stringsAsFactors = TRUE)
-                data1[[i1]][, "fake_y"] <- as.numeric(data1[[i1]][, "fake_y"])
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT ASSOCIATED TO ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT ", geom[[i1]], " -> FAKE COLUMN ADDED TO DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", NAMED \"fake_y\" FOR FINAL DRAWING")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }else{
-            if(all(geom[[i1]] == "geom_vline")){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ": y ARGUMENT MUST BE NULL IF ", ifelse(length(geom)== 1L, "geom", paste0("geom NUMBER ", i1)), " ARGUMENT IS \"geom_vline\"")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-            tempo <- fun_check(data = y[[i1]], data.name = ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), class = "vector", mode = "character", length = 1, fun.name = function.name)
-            if(tempo$problem == TRUE){
-                stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        # x[[i1]] and y[[i1]] not NULL anymore
-        if( ! (x[[i1]] %in% names(data1[[i1]]))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(x[[i1]], collapse = " "))))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        if( ! (y[[i1]] %in% names(data1[[i1]]))){
-            tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(y[[i1]], collapse = " "))))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        tempo <- fun_check(data = data1[[i1]][, x[[i1]]], data.name = ifelse(length(x)== 1L, "x ARGUMENT (AS COLUMN NAME OF data1 DATA FRAME)", paste0("ELEMENT ", i1, " OF x ARGUMENT", " (AS COLUMN NAME OF data1 DATA FRAME NUMBER ", i1, ")")), class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        tempo <- fun_check(data = data1[[i1]][, y[[i1]]], data.name = ifelse(length(y)== 1L, "y ARGUMENT (AS COLUMN NAME OF data1 DATA FRAME)", paste0("ELEMENT ", i1, " OF y ARGUMENT", " (AS COLUMN NAME OF data1 DATA FRAME NUMBER ", i1, ")")), class = "vector", mode = "numeric", na.contain = TRUE, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        if(x[[i1]] == "fake_x" & y[[i1]] == "fake_y"){ # because the code cannot accept to be both "fake_x" and "fake_y" at the same time
-            tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 2\nTHE CODE CANNOT ACCEPT x AND y TO BE \"fake_x\" AND \"fake_y\" IN THE SAME DATA FRAME ", i1, " ")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-        
-        if(( ! is.null(categ)) & ( ! is.null(categ[[i1]]))){ # is.null(categ[[i1]]) works even if categ is NULL # is.null(categ[[i1]]) works even if categ is NULL # if categ[[i1]] = NULL, fake_categ will be created later on
-            tempo <- fun_check(data = categ[[i1]], data.name = ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")),, class = "vector", mode = "character", length = 1, fun.name = function.name)
-            if(tempo$problem == TRUE){
-                stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-            if( ! (categ[[i1]] %in% names(data1[[i1]]))){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT MUST BE A COLUMN NAME OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT\nHERE IT IS: ", paste(categ[[i1]], collapse = " "))))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-            tempo1 <- fun_check(data = data1[[i1]][, categ[[i1]]], data.name = ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name)
-            tempo2 <- fun_check(data = data1[[i1]][, categ[[i1]]], data.name = ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), class = "factor", na.contain = TRUE, fun.name = function.name)
-            if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " MUST BE A FACTOR OR CHARACTER VECTOR")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if(tempo1$problem == FALSE){
-                data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE CHARACTER COLUMN HAS BEEN CONVERTED TO FACTOR")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                
-            }
-            if(geom[[i1]] == "geom_vline" | geom[[i1]] == "geom_hline"){
-                if(length(unique(data1[[i1]][, categ[[i1]]])) != nrow(data1[[i1]])){
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(geom)== 1L, "geom OF data1 ARGUMENT", paste0("geom NUMBER ", i1, " OF DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " ARGUMENT IS ", geom[[i1]], ", MEANING THAT ", ifelse(length(categ)== 1L, "categ OF data1 ARGUMENT", paste0("ELEMENT ", i1, " OF categ ARGUMENT IN DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " MUST HAVE A DIFFERENT CLASS PER LINE OF data1 (ONE x VALUE PER CLASS)")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }
-            }
-        }else if(( ! is.null(categ)) & is.null(categ[[i1]])){ # is.null(categ[[i1]]) works even if categ is NULL # if categ[[i1]] = NULL, fake_categ will be created. WARNING: is.null(categ[[i1]]) means no legend display (see above), because categ has not been precised. This also means a single color for data1[[i1]]
-            if(length(color[[i1]]) > 1){ # 0 means is.null(color[[i1]]) or is.null(color) and 1 is ok -> single color for data1[[i1]]
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT BUT CORRESPONDING COLORS IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " HAS LENGTH OVER 1\n", paste(color[[i1]], collapse = " "), "\nWHICH IS NOT COMPATIBLE WITH NULL CATEG -> COLOR RESET TO A SINGLE COLOR")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                color[i1] <- list(NULL) # will provide a single color below # Warning color[[i1]] <- NULL removes the compartment
-            }
-            categ[[i1]] <- "fake_categ"
-            data1[[i1]] <- cbind(data1[[i1]], fake_categ = "", stringsAsFactors = TRUE)
-            # inactivated because give a different color to different "Line_" categ while a single color for all the data1[[i1]] required. Thus, put back after the color management
-            # if(geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline"){
-            # data1[[i1]][, "fake_categ"] <- paste0("Line_", 1:nrow(data1[[i1]]))
-            # }else{
-            data1[[i1]][, "fake_categ"] <- data1[[i1]][, "fake_categ"] # as.numeric("") create a vector of NA but class numeric
-            # }
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NULL ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ")), " ARGUMENT -> FOR DATA FRAME ", ifelse(length(data1)== 1L, "data1 ARGUMENT:", paste0("NUMBER ", i1, " OF data1 ARGUMENT:")), "\n- FAKE \"fake_categ\" COLUMN ADDED FILLED WITH \"\"(OR WITH \"Line_...\" FOR LINES)\n- SINGLE COLOR USED FOR PLOTTING\n- NO LEGEND DISPLAYED")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        # OK: if categ is not NULL, all the non-null categ columns of data1 are factors from here
-        
-        # management of log scale and Inf removal
-        if(x[[i1]] != "fake_x"){
-            if(any(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN ", ifelse(length(categ)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        if(y[[i1]] != "fake_y"){
-            if(any(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[, y])) & ( ! is.na(data1[, y])) detects only Inf
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") PRESENCE OF -Inf OR Inf VALUES IN ", ifelse(length(categ)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        # log conversion
-        if(x.log != "no"){
-            tempo1 <- ! is.finite(data1[[i1]][, x[[i1]]]) # where are initial NA and Inf
-            data1[[i1]][, x[[i1]]] <- suppressWarnings(get(x.log)(data1[[i1]][, x[[i1]]]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-            if(any( ! (tempo1 | is.finite(data1[[i1]][, x[[i1]]])))){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN ", ifelse(length(categ)== 1L, "x", paste0("ELEMENT ", i1, " OF x ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        if(y.log != "no"){
-            tempo1 <- ! is.finite(data1[[i1]][, y[[i1]]]) # where are initial NA and Inf
-            data1[[i1]][, y[[i1]]] <- suppressWarnings(get(y.log)(data1[[i1]][, y[[i1]]]))# no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-            if(any( ! (tempo1 | is.finite(data1[[i1]][, y[[i1]]])))){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") LOG CONVERSION INTRODUCED -Inf OR Inf OR NaN VALUES IN ", ifelse(length(categ)== 1L, "y", paste0("ELEMENT ", i1, " OF y ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-        }
-        # Inf removal
-        # removed.row.nb[[i1]] <- NULL # already NULL and Warning this removes the compartment
-        removed.rows[[i1]] <- data.frame(stringsAsFactors = FALSE)
-        if(any(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]])) detects only Inf
-            removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], which(( ! is.finite(data1[[i1]][, x[[i1]]])) & ( ! is.na(data1[[i1]][, x[[i1]]]))))
-        }
-        if(any(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])))){ # is.finite also detects NA: ( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]])) detects only Inf
-            removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], which(( ! is.finite(data1[[i1]][, y[[i1]]])) & ( ! is.na(data1[[i1]][, y[[i1]]]))))
-        }
-        if( ! is.null(removed.row.nb[[i1]])){
-            removed.row.nb[[i1]] <- unique(removed.row.nb[[i1]]) # to remove the duplicated positions (NA in both x and y)
-            removed.rows[[i1]] <- rbind(removed.rows[[i1]], data1.ini[[i1]][removed.row.nb[[i1]], ]) # here data1.ini used to have the y = O rows that will be removed because of Inf creation after log transformation
-            data1[[i1]] <- data1[[i1]][-removed.row.nb[[i1]], ]
-            data1.ini[[i1]] <- data1.ini[[i1]][-removed.row.nb[[i1]], ] #
-        }
-        # From here, data1 and data.ini have no more Inf
-        # end Inf removal
-        # x.lim and y.lim dealt later on, after the end f the loop
-        # end management of log scale and Inf removal
-        # management of log scale
-        if(x.log != "no"){
-            data1[[i1]][, x[[i1]]] <- suppressWarnings(get(x.log)(data1[[i1]][, x[[i1]]])) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-        }
-        if(y.log != "no"){
-            data1[[i1]][, y[[i1]]] <- suppressWarnings(get(y.log)(data1[[i1]][, y[[i1]]])) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-        }
-        # end management of log scale
-        # na detection and removal
-        column.check <- unique(unlist(c( # unlist because creates a list
-            if(x[[i1]] == "fake_x"){NULL}else{x[[i1]]}, 
-            if(y[[i1]] == "fake_y"){NULL}else{y[[i1]]}, 
-            if( ! is.null(categ)){if(is.null(categ[[i1]])){NULL}else{categ[[i1]]}}, 
-            if( ! is.null(facet.categ)){if(is.null(facet.categ[[i1]])){NULL}else{facet.categ[[i1]]}}
-        ))) # dot.categ because can be a 3rd column of data1
-        if(any(is.na(data1[[i1]][, column.check]))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NA DETECTED IN COLUMNS ", paste(column.check, collapse = " "), " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " AND CORRESPONDING ROWS REMOVED (SEE $removed.row.nb AND $removed.rows)")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            for(i3 in 1:length(column.check)){
-                if(any(is.na(data1[[i1]][, column.check[i3]]))){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("NA REMOVAL DUE TO COLUMN ", column.check[i3], " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-            tempo <- unique(unlist(lapply(lapply(c(data1[[i1]][column.check]), FUN = is.na), FUN = which)))
-            removed.row.nb[[i1]] <- c(removed.row.nb[[i1]], tempo)
-            removed.rows[[i1]] <- rbind(removed.rows[[i1]], data1.ini[[i1]][tempo, ]) #  # tempo used because removed.row.nb is not empty. Here data1.ini used to have the non NA rows that will be removed because of NAN creation after log transformation (neg values for instance)
-            column.check <- column.check[ ! (column.check == x[[i1]] | column.check == y[[i1]])] # remove x and y to keep quali columns
-            if(length(tempo) != 0){
-                data1[[i1]] <- data1[[i1]][-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers thant the former
-                data1.ini[[i1]] <- data1.ini[[i1]][-tempo, ] # WARNING tempo here and not removed.row.nb because the latter contain more numbers than the former
-                for(i4 in 1:length(column.check)){
-                    if(any( ! unique(removed.rows[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]]))){
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count,") IN COLUMN ", column.check[i4], " OF ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE FOLLOWING CLASSES HAVE DISAPPEARED AFTER NA REMOVAL\n(IF COLUMN USED IN THE PLOT, THIS CLASS WILL NOT BE DISPLAYED):\n", paste(unique(removed.rows[[i1]][, column.check[i4]])[ ! unique(removed.rows[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]])], collapse = " "))
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                        tempo.levels <- levels(data1[[i1]][, column.check[i4]])[levels(data1[[i1]][, column.check[i4]]) %in% unique(as.character(data1[[i1]][, column.check[i4]]))]
-                        data1[[i1]][, column.check[i4]] <- factor(as.character(data1[[i1]][, column.check[i4]]), levels = tempo.levels)
-                        if(column.check[i4] %in% categ[[i1]] & ! is.null(categ.class.order)){
-                            categ.class.order[[i1]] <- levels(data1[[i1]][, column.check[i4]])[levels(data1[[i1]][, column.check[i4]]) %in% unique(data1[[i1]][, column.check[i4]])] # remove the absent class in the categ.class.order vector
-                            data1[[i1]][, column.check[i4]] <- factor(as.character(data1[[i1]][, column.check[i4]]), levels = unique(categ.class.order[[i1]]))
-                        }
-                    }
-                }
-            }
-        }
-        # end na detection and removal
-        # From here, data1 and data.ini have no more NA or NaN in x, y, categ (if categ != NULL) and facet.categ (if categ != NULL)
-        if( ! is.null(categ.class.order)){
-            # the following check will be done several times but I prefer to keep it here, after the creation of categ
-            if(is.null(categ[[i1]]) & ! is.null(categ.class.order[[i1]])){
-                tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ ARGUMENT CANNOT BE NULL IF COMPARTMENT ", i1, " OF categ.class.order ARGUMENT IS NOT NULL: ", paste(categ.class.order, collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else{
-                if(is.null(categ.class.order[[i1]])){
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") THE categ.class.order COMPARTMENT ", i1, " IS NULL. ALPHABETICAL ORDER WILL BE APPLIED")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    data1[[i1]][, categ[[i1]]] <- factor(as.character(data1[[i1]][, categ[[i1]]])) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                    categ.class.order[[i1]] <- levels(data1[[i1]][, categ[[i1]]]) # character vector that will be used later
-                }else{
-                    tempo <- fun_check(data = categ.class.order[[i1]], data.name = paste0("COMPARTMENT ", i1 , " OF categ.class.order ARGUMENT"), class = "vector", mode = "character", length = length(levels(data1[[i1]][, categ[[i1]]])), fun.name = function.name) # length(data1[, categ[i1]) -> if data1[, categ[i1] was initially character vector, then conversion as factor after the NA removal, thus class number ok. If data1[, categ[i1] was initially factor, no modification after the NA removal, thus class number ok
-                    if(tempo$problem == TRUE){
-                        stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                    }
-                }
-                if(any(duplicated(categ.class.order[[i1]]))){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ.class.order ARGUMENT CANNOT HAVE DUPLICATED CLASSES: ", paste(categ.class.order[[i1]], collapse = " "))
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }else if( ! (all(categ.class.order[[i1]] %in% unique(data1[[i1]][, categ[[i1]]])) & all(unique(data1[[i1]][, categ[[i1]]]) %in% categ.class.order[[i1]]))){
-                    tempo.cat <- paste0("ERROR IN ", function.name, "\nCOMPARTMENT ", i1, " OF categ.class.order ARGUMENT MUST BE CLASSES OF COMPARTMENT ", i1, " OF categ ARGUMENT\nHERE IT IS:\n", paste(categ.class.order[[i1]], collapse = " "), "\nFOR COMPARTMENT ", i1, " OF categ.class.order AND IT IS:\n", paste(unique(data1[[i1]][, categ[[i1]]]), collapse = " "), "\nFOR COLUMN ", categ[[i1]], " OF data1 NUMBER ", i1)
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }else{
-                    data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]], levels = categ.class.order[[i1]]) # reorder the factor
-                }
-                names(categ.class.order)[i1] <- categ[[i1]]
-            }
-        }
-        # OK: if categ.class.order is not NULL, all the NULL categ.class.order columns of data1 are character from here
-        
-        if( ! is.null(legend.name[[i1]])){
-            tempo <- fun_check(data = legend.name[[i1]], data.name = ifelse(length(legend.name)== 1L, "legend.name", paste0("legend.name NUMBER ", i1)),, class = "vector", mode = "character", length = 1, fun.name = function.name)
-            if(tempo$problem == TRUE){
-                stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-        if( ! is.null(color)){ # if color is NULL, will be filled later on
-            # check the nature of color
-            if(is.null(color[[i1]])){
-                compart.null.color <- compart.null.color + 1
-                color[[i1]] <- grey(compart.null.color / 8) # cannot be more than 7 overlays. Thus 7 different greys. 8/8 is excluded because white dots
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") NULL COLOR IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " ASSOCIATED TO ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", SINGLE COLOR ", paste(color[[i1]], collapse = " "), " HAS BEEN ATTRIBUTED")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            tempo1 <- fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "vector", mode = "character", na.contain = TRUE, fun.name = function.name) # na.contain = TRUE in case of colum of data1
-            tempo2 <- fun_check(data = color[[i1]], data.name = ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), class = "factor", na.contain = TRUE, fun.name = function.name) # idem
-            if(tempo1$problem == TRUE & tempo2$problem == TRUE){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A FACTOR OR CHARACTER VECTOR OR INTEGER VECTOR") # integer possible because dealt above
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if( ! (all(color[[i1]] %in% colors() | grepl(pattern = "^#", color[[i1]])))){ # check that all strings of low.color start by #
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A HEXADECIMAL COLOR VECTOR STARTING BY # AND/OR COLOR NAMES GIVEN BY colors(): ", paste(unique(color[[i1]]), collapse = " "))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-            if(any(is.na(color[[i1]]))){
-                warn.count <- warn.count + 1
-                tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), ", THE COLORS:\n", paste(unique(color[[i1]]), collapse = " "), "\nCONTAINS NA")
-                warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            }
-            # end check the nature of color
-            # check the length of color
-            if(is.null(categ) & length(color[[i1]]) != 1){
-                tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A SINGLE COLOR IF categ IS NULL")
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }else if( ! is.null(categ)){
-                # No problem of NA management by ggplot2 because already removed
-                if(categ[[i1]] == "fake_categ" & length(color[[i1]]) != 1){
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE A SINGLE COLOR IF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IS NULL")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }else if(length(color[[i1]]) == length(unique(data1[[i1]][, categ[[i1]]]))){ # here length(color) is equal to the different number of categ
-                    data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", THE FOLLOWING COLORS:\n", paste(color[[i1]], collapse = " "), "\nHAVE BEEN ATTRIBUTED TO THESE CLASSES:\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }else if(length(color[[i1]]) == length(data1[[i1]][, categ[[i1]]])){# here length(color) is equal to nrow(data1[[i1]]) -> Modif to have length(color) equal to the different number of categ (length(color) == length(levels(data1[[i1]][, categ[[i1]]])))
-                    data1[[i1]] <- cbind(data1[[i1]], color = color[[i1]], stringsAsFactors = TRUE)
-                    tempo.check <- unique(data1[[i1]][ , c(categ[[i1]], "color")])
-                    if( ! (nrow(data1[[i1]]) == length(color[[i1]]) & nrow(tempo.check) == length(unique(data1[[i1]][ , categ[[i1]]])))){
-                        tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color")), " ARGUMENT HAS THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nBUT IS INCORRECTLY ASSOCIATED TO EACH CLASS OF THIS categ:\n", paste(unique(mapply(FUN = "paste", data1[[i1]][ ,categ[[i1]]], data1[[i1]][ ,"color"])), collapse = "\n"))
-                        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                    }else{
-                        data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                        color[[i1]] <- unique(color[[i1]][order(data1[[i1]][, categ[[i1]]])]) # Modif to have length(color) equal to the different number of categ (length(color) == length(levels(data1[[i1]][, categ[[i1]]])))
-                        warn.count <- warn.count + 1
-                        tempo.warn <- paste0("(", warn.count, ") FROM FUNCTION ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " HAS THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " COLUMN VALUES\nCOLORS HAVE BEEN RESPECTIVELY ASSOCIATED TO EACH CLASS OF categ AS:\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "), "\n", paste(color[[i1]], collapse = " "))
-                        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    }
-                }else if(length(color[[i1]])== 1L){
-                    data1[[i1]][, categ[[i1]]] <- factor(data1[[i1]][, categ[[i1]]]) # if already a factor, change nothing, if characters, levels according to alphabetical order
-                    color[[i1]] <- rep(color[[i1]], length(levels(data1[[i1]][, categ[[i1]]])))
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") IN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), ", COLOR HAS LENGTH 1 MEANING THAT ALL THE DIFFERENT CLASSES OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), "\n", paste(levels(factor(data1[[i1]][, categ[[i1]]])), collapse = " "), "\nWILL HAVE THE SAME COLOR\n", paste(color[[i1]], collapse = " "))
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }else{
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST BE\n(1) LENGTH 1\nOR (2) THE LENGTH OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), " COLUMN VALUES\nOR (3) THE LENGTH OF THE CLASSES IN THIS COLUMN\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LENGTH ", length(data1[[i1]][, categ[[i1]]]), " AND CATEG CLASS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])), "\nPRESENCE OF NA IN THE COLUMN x, y OR categ OF data1 COULD BE THE PROBLEME")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }
-            }
-        }
-        if((geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline") & ! is.null(categ[[i1]])){ # add here after the color management, to deal with the different lines to plot inside any data[[i1]]
-            if(categ[[i1]] == "fake_categ"){
-                data1[[i1]][, "fake_categ"] <- factor(paste0("Line_", formatC(1:nrow(data1[[i2]]), width = nchar(nrow(data1[[i2]])), flag = "0")))
-            }
-        }
-        tempo <- fun_check(data = alpha[[i1]], data.name = ifelse(length(alpha)== 1L, "alpha", paste0("alpha NUMBER ", i1)), prop = TRUE, length = 1, fun.name = function.name)
-        if(tempo$problem == TRUE){
-            stop(paste0("\n\n================\n\n", tempo$text, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    # end loop (checking inside list compartment)
-    if(length(data1) > 1){
-        if(length(unique(unlist(x)[ ! x == "fake_x"])) > 1){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE x ARGUMENT DOES NOT CONTAIN IDENTICAL COLUMN NAMES:\n", paste(unlist(x), collapse = " "), "\nX-AXIS OVERLAYING DIFFERENT VARIABLES?")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    if(length(data1) > 1){
-        if(length(unique(unlist(y)[ ! y == "fake_y"])) > 1){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE y ARGUMENT DOES NOT CONTAIN IDENTICAL COLUMN NAMES:\n", paste(unlist(y), collapse = " "), "\nY-AXIS OVERLAYING DIFFERENT VARIABLES?")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    if(sum(geom %in% "geom_point") > 3){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT HAVE MORE THAN THREE \"geom_point\" ELEMENTS")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }else if(length(geom) - sum(geom %in% "geom_point") > 3){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": geom ARGUMENT CANNOT HAVE MORE THAN THREE LINE ELEMENTS")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    # x.lim management before transfo by x.log
-    if(x.log != "no" & ! is.null(x.lim)){
-        if(any(x.lim <= 0)){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE x.log ARGUMENT SET TO ", x.log, ":\n", paste(x.lim, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(any( ! is.finite(if(x.log == "log10"){log10(x.lim)}else{log2(x.lim)}))){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT RETURNS INF/NA WITH THE x.log ARGUMENT SET TO ", x.log, "\nAS SCALE COMPUTATION IS ", ifelse(x.log == "log10", "log10", "log2"), ":\n", paste(if(x.log == "log10"){log10(x.lim)}else{log2(x.lim)}, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    if(x.log != "no" & x.include.zero == TRUE){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") x.log ARGUMENT SET TO ", x.log, " AND x.include.zero ARGUMENT SET TO TRUE -> x.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        x.include.zero <- FALSE
-    }
-    # end x.lim management before transfo by x.log
-    # y.lim management before transfo by y.log
-    if(y.log != "no" & ! is.null(y.lim)){
-        if(any(y.lim <= 0)){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(any( ! is.finite(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}))){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT RETURNS INF/NA WITH THE y.log ARGUMENT SET TO ", y.log, "\nAS SCALE COMPUTATION IS ", ifelse(y.log == "log10", "log10", "log2"), ":\n", paste(if(y.log == "log10"){log10(y.lim)}else{log2(y.lim)}, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    if(y.log != "no" & y.include.zero == TRUE){
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") y.log ARGUMENT SET TO ", y.log, " AND y.include.zero ARGUMENT SET TO TRUE -> y.include.zero ARGUMENT RESET TO FALSE BECAUSE 0 VALUE CANNOT BE REPRESENTED IN LOG SCALE")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        y.include.zero <- FALSE
-    }
-    # end y.lim management before transfo by y.log
-    # end other checkings
-    # reserved word checking
-    #already done above
-    # end reserved word checking
-    # end second round of checking and data preparation
-    
-    
-    # package checking
-    fun_pack(req.package = c(
-        "gridExtra", 
-        "ggplot2", 
-        "lemon", 
-        "scales"
-    ), lib.path = lib.path)
-    # packages Cairo and grid tested by fun_gg_point_rast()
-    # end package checking
-    
-    
-    
-    
-    # main code
-    # axes management
-    if(is.null(x.lim)){
-        if(any(unlist(mapply(FUN = "[[", data1, x, SIMPLIFY = FALSE)) %in% c(Inf, -Inf))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE x COLUMN IN data1 CONTAINS -Inf OR Inf VALUES THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        x.lim <- suppressWarnings(range(unlist(mapply(FUN = "[[", data1, x, SIMPLIFY = FALSE)), na.rm = TRUE, finite = TRUE)) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only. y.lim added here. If NULL, ok if y argument has values
-    }else if(x.log != "no"){
-        x.lim <- get(x.log)(x.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-    }
-    if(x.log != "no"){
-        if(any( ! is.finite(x.lim))){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\nx.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE x.log ARGUMENT SET TO ", x.log, ":\n", paste(x.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    if(suppressWarnings(all(x.lim %in% c(Inf, -Inf)))){ # happen when x is only NULL
-        if(all(unlist(geom) %in% c("geom_vline", "geom_stick"))){
-            tempo.cat <- paste0("ERROR IN ", function.name, " NOT POSSIBLE TO DRAW geom_vline OR geom_stick KIND OF LINES ALONE IF x.lim ARGUMENT IS SET TO NULL, SINCE NO X-AXIS DEFINED (", ifelse(length(x)== 1L, "x", paste0("ELEMENT ", i1, " OF x")), " ARGUMENT MUST BE NULL FOR THESE KIND OF LINES)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, " x.lim ARGUMENT MADE OF NA, -Inf OR Inf ONLY: ", paste(x.lim, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    x.lim.order <- order(x.lim) # to deal with inverse axis
-    # print(x.lim.order)
-    x.lim <- sort(x.lim)
-    x.lim[1] <- x.lim[1] - abs(x.lim[2] - x.lim[1]) * ifelse(diff(x.lim.order) > 0, x.right.extra.margin, x.left.extra.margin) # diff(x.lim.order) > 0 means not inversed axis
-    x.lim[2] <- x.lim[2] + abs(x.lim[2] - x.lim[1]) * ifelse(diff(x.lim.order) > 0, x.left.extra.margin, x.right.extra.margin) # diff(x.lim.order) > 0 means not inversed axis
-    if(x.include.zero == TRUE){ # no need to check x.log != "no" because done before
-        x.lim <- range(c(x.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    }
-    x.lim <- x.lim[x.lim.order]
-    if(any(is.na(x.lim))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 3")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    if(is.null(y.lim)){
-        if(any(unlist(mapply(FUN = "[[", data1, y, SIMPLIFY = FALSE)) %in% c(Inf, -Inf))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE y COLUMN IN data1 CONTAINS -Inf OR Inf VALUES THAT WILL NOT BE CONSIDERED IN THE PLOT RANGE")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-        y.lim <- suppressWarnings(range(unlist(mapply(FUN = "[[", data1, y, SIMPLIFY = FALSE)), na.rm = TRUE, finite = TRUE)) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only. y.lim added here. If NULL, ok if y argument has values
-    }else if(y.log != "no"){
-        y.lim <- get(y.log)(y.lim) # no env = sys.nframe(), inherit = FALSE in get() because look for function in the classical scope
-    }
-    if(y.log != "no"){
-        if(any( ! is.finite(y.lim))){
-            tempo.cat <- paste0("ERROR IN ", function.name, "\ny.lim ARGUMENT CANNOT HAVE ZERO OR NEGATIVE VALUES WITH THE y.log ARGUMENT SET TO ", y.log, ":\n", paste(y.lim, collapse = " "), "\nPLEASE, CHECK DATA VALUES (PRESENCE OF ZERO OR INF VALUES)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    if(suppressWarnings(all(y.lim %in% c(Inf, -Inf)))){ # happen when y is only NULL
-        if(all(unlist(geom) == "geom_vline")){
-            tempo.cat <- paste0("ERROR IN ", function.name, " NOT POSSIBLE TO DRAW geom_vline KIND OF LINES ALONE IF y.lim ARGUMENT IS SET TO NULL, SINCE NO Y-AXIS DEFINED (", ifelse(length(y)== 1L, "y", paste0("ELEMENT ", i1, " OF y")), " ARGUMENT MUST BE NULL FOR THESE KIND OF LINES)")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else{
-            tempo.cat <- paste0("ERROR IN ", function.name, " y.lim ARGUMENT MADE OF NA, -Inf OR Inf ONLY: ", paste(y.lim, collapse = " "))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    y.lim.order <- order(y.lim) # to deal with inverse axis
-    y.lim <- sort(y.lim)
-    y.lim[1] <- y.lim[1] - abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.bottom.extra.margin, y.top.extra.margin) # diff(y.lim.order) > 0 means not inversed axis
-    y.lim[2] <- y.lim[2] + abs(y.lim[2] - y.lim[1]) * ifelse(diff(y.lim.order) > 0, y.top.extra.margin, y.bottom.extra.margin) # diff(y.lim.order) > 0 means not inversed axis
-    if(y.include.zero == TRUE){ # no need to check y.log != "no" because done before
-        y.lim <- range(c(y.lim, 0), na.rm = TRUE, finite = TRUE) # finite = TRUE removes all the -Inf and Inf except if only this. In that case, whatever the -Inf and/or Inf present, output -Inf;Inf range. Idem with NA only
-    }
-    y.lim <- y.lim[y.lim.order]
-    if(any(is.na(y.lim))){
-        tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 4")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    # end axes management
-    
-    
-    
-    
-    # create a fake categ if NULL to deal with legend display
-    if(is.null(categ)){
-        categ <- vector("list", length(data1))
-        categ[] <- "fake_categ"
-        for(i2 in 1:length(data1)){
-            data1[[i2]] <- cbind(data1[[i2]], fake_categ = "", stringsAsFactors = TRUE)
-            if(geom[[i2]] == "geom_hline" | geom[[i2]] == "geom_vline"){
-                data1[[i2]][, "fake_categ"] <- factor(paste0("Line_", 1:nrow(data1[[i2]])))
-            }
-        }
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") NULL categ ARGUMENT -> FAKE \"fake_categ\" COLUMN ADDED TO EACH DATA FRAME OF data1, AND FILLED WITH \"\"")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
-    # categ is not NULL anymore
-    if(is.null(categ.class.order)){
-        categ.class.order <- vector("list", length = length(data1))
-        tempo.categ.class.order <- NULL
-        for(i2 in 1:length(categ.class.order)){
-            categ.class.order[[i2]] <- levels(data1[[i2]][, categ[[i2]]])
-            names(categ.class.order)[i2] <- categ[[i2]]
-            tempo.categ.class.order <- c(tempo.categ.class.order, ifelse(i2 != 1, "\n", ""), categ.class.order[[i2]])
-        }
-        if(any(unlist(legend.disp))){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") THE categ.class.order SETTING IS NULL. ALPHABETICAL ORDER WILL BE APPLIED FOR CLASS ORDERING:\n", paste(tempo.categ.class.order, collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end create a fake categ if NULL to deal with legend display
-    # categ.class.order is not NULL anymore
-    
-    
-    # vector of color with length as in levels(categ) of data1
-    if(is.null(color)){
-        color <- vector("list", length(data1))
-        length.categ.list <- lapply(lapply(mapply(FUN = "[[", data1, categ, SIMPLIFY = FALSE), FUN = unique), FUN = function(x){length(x[ ! is.na(x)])})
-        length.categ.list[sapply(categ, FUN = "==", "fake_categ")] <- 1 # when is.null(color), a single color for all the dots or lines of data[[i1]] that contain "fake_categ" category
-        total.categ.length <- sum(unlist(length.categ.list), na.rm = TRUE)
-        tempo.color <- fun_gg_palette(total.categ.length)
-        tempo.count <- 0
-        for(i2 in 1:length(data1)){
-            color[[i2]] <- tempo.color[(1:length.categ.list[[i2]]) + tempo.count]
-            tempo.count <- tempo.count + length.categ.list[[i2]]
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") NULL color ARGUMENT -> COLORS RESPECTIVELY ATTRIBUTED TO EACH CLASS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i2, " OF categ ARGUMENT")), " (", categ[[i2]], ") IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i2, " OF data1 ARGUMENT")), ":\n", paste(color[[i2]], collapse = " "), "\n", paste(if(all(levels(data1[[i2]][, categ[[i2]]]) == "")){'\"\"'}else{levels(data1[[i2]][, categ[[i2]]])}, collapse = " "))
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end vector of color with length as in levels(categ) of data1
-    # color is not NULL anymore
-    
-    
-    
-    
-    
-    # last check
-    for(i1 in 1:length(data1)){
-        if(categ[[i1]] != "fake_categ" & length(color[[i1]]) != length(unique(data1[[i1]][, categ[[i1]]]))){
-            tempo.cat <- paste0("ERROR IN ", function.name, " LAST CHECK: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE THE LENGTH OF LEVELS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LEVELS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])), "\nREMINDER: A SINGLE COLOR PER CLASS OF CATEG AND A SINGLE CLASS OF CATEG PER COLOR MUST BE RESPECTED")
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }else if(categ[[i1]] == "fake_categ" & length(color[[i1]]) != 1){
-            tempo.cat <- paste0("ERROR IN ", function.name, " LAST CHECK: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE LENGTH 1 WHEN ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IS NULL\nHERE IT IS COLOR LENGTH ", length(color[[i1]]))
-            stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-        }
-    }
-    # end last check
-    
-    
-    
-    
-    
-    # conversion of geom_hline and geom_vline
-    for(i1 in 1:length(data1)){
-        if(geom[[i1]] == "geom_hline" | geom[[i1]] == "geom_vline"){
-            final.data.frame <- data.frame()
-            for(i3 in 1:nrow(data1[[i1]])){
-                tempo.data.frame <- rbind(data1[[i1]][i3, ], data1[[i1]][i3, ], stringsAsFactors = TRUE)
-                if(geom[[i1]] == "geom_hline"){
-                    tempo.data.frame[, x[[i1]]] <- x.lim
-                }else if(geom[[i1]] == "geom_vline"){
-                    tempo.data.frame[, y[[i1]]] <- y.lim
-                }else{
-                    tempo.cat <- paste0("ERROR IN ", function.name, ": CODE INCONSISTENCY 5")
-                    stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-                }
-                # 3 lines below inactivated because I put that above
-                # if(is.null(categ[[i1]])){
-                # data1[, "fake_categ"] <- paste0("Line_", i3)
-                # }
-                final.data.frame <- rbind(final.data.frame, tempo.data.frame, stringsAsFactors = TRUE)
-            }
-            data1[[i1]] <- final.data.frame
-            geom[[i1]] <- "geom_line"
-            if(length(color[[i1]])== 1L){
-                color[[i1]] <- rep(color[[i1]], length(unique(data1[[i1]][ , categ[[i1]]])))
-            }else if(length(color[[i1]]) != length(unique(data1[[i1]][ , categ[[i1]]]))){
-                tempo.cat <- paste0("ERROR IN ", function.name, " geom_hline AND geom_vline CONVERSION TO FIT THE XLIM AND YLIM LIMITS OF THE DATA: ", ifelse(length(color)== 1L, "color", paste0("ELEMENT NUMBER ", i1, " OF color ARGUMENT")), " MUST HAVE THE LENGTH OF LEVELS OF ", ifelse(length(categ)== 1L, "categ", paste0("ELEMENT ", i1, " OF categ ARGUMENT")), " IN ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i1, " OF data1 ARGUMENT")), "\nHERE IT IS COLOR LENGTH ", length(color[[i1]]), " VERSUS CATEG LEVELS LENGTH ", length(unique(data1[[i1]][, categ[[i1]]])))
-                stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-            }
-        }
-    }
-    # end conversion of geom_hline and geom_vline
-    
-    
-    
-    
-    # kind of geom_point (vectorial or raster)
-    scatter.kind <- vector("list", length = length(data1)) # list of same length as data1, that will be used to use either ggplot2::geom_point() (vectorial dot layer) or fun_gg_point_rast() (raster dot layer)
-    fix.ratio <- FALSE
-    if(is.null(raster.threshold)){
-        if(raster == TRUE){
-            scatter.kind[] <- "fun_gg_point_rast" # not important to fill everything: will be only used when geom == "geom_point"
-            fix.ratio <- TRUE
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") RASTER PLOT GENERATED -> ASPECT RATIO OF THE PLOT REGION SET BY THE raster.ratio ARGUMENT (", fun_round(raster.ratio, 2), ") TO AVOID A BUG OF ELLIPSOID DOT DRAWING")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }else{
-            scatter.kind[] <- "ggplot2::geom_point"
-        }
-    }else{
-        for(i2 in 1:length(data1)){
-            if(geom[[i2]] == "geom_point"){
-                if(nrow(data1[[i2]]) <= raster.threshold){
-                    scatter.kind[[i2]] <- "ggplot2::geom_point"
-                }else{
-                    scatter.kind[[i2]] <- "fun_gg_point_rast"
-                    fix.ratio <- TRUE
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") ", ifelse(length(data1)== 1L, "data1 ARGUMENT", paste0("DATA FRAME NUMBER ", i2, " OF data1 ARGUMENT")), " LAYER AS RASTER (NOT VECTORIAL)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                }
-            }
-        }
-        if(any(unlist(scatter.kind) == "fun_gg_point_rast")){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") RASTER PLOT GENERATED -> ASPECT RATIO OF THE PLOT REGION SET BY THE raster.ratio ARGUMENT (", fun_round(raster.ratio, 2), ") TO AVOID A BUG OF ELLIPSOID DOT DRAWING")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }
-    # end kind of geom_point (vectorial or raster)
-    
-    
-    
-    
-    # no need loop part
-    coord.names <- NULL
-    tempo.gg.name <- "gg.indiv.plot."
-    tempo.gg.count <- 0
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::ggplot()", if(is.null(add)){""}else{add})))) # add added here to have the facets
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::xlab(if(is.null(x.lab)){x[[1]]}else{x.lab}))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ylab(if(is.null(y.lab)){y[[1]]}else{y.lab}))
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::ggtitle(title))
-    # text angle management
-    x.tempo.just <- fun_gg_just(angle = x.text.angle, pos = "bottom", kind = "axis")
-    y.tempo.just <- fun_gg_just(angle = y.text.angle, pos = "left", kind = "axis")
-    # end text angle management
-    add.check <- TRUE
-    if( ! is.null(add)){ # if add is NULL, then = 0
-        if(grepl(pattern = "ggplot2::theme", add) == TRUE){
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") \"ggplot2::theme\" STRING DETECTED IN THE add ARGUMENT\n-> INTERNAL GGPLOT2 THEME FUNCTIONS theme() AND theme_classic() HAVE BEEN INACTIVATED, TO BE USED BY THE USER\n-> article ARGUMENT WILL BE IGNORED\nIT IS RECOMMENDED TO USE \"+ theme(aspect.ratio = raster.ratio)\" IF RASTER MODE IS ACTIVATED")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-            add.check <- FALSE
-        }
-    }
-    if(add.check == TRUE & article == TRUE){
-        # WARNING: not possible to add several times theme(). NO message but the last one overwrites the others
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::theme_classic(base_size = text.size))
-        if(grid == TRUE){
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-                text = ggplot2::element_text(size = text.size), 
-                plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-                legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-                line = ggplot2::element_line(size = 0.5), 
-                axis.line.y.left = ggplot2::element_line(colour = "black"), # draw lines for the y axis
-                axis.line.x.bottom = ggplot2::element_line(colour = "black"), # draw lines for the x axis
-                panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
-                panel.grid.minor.x = ggplot2::element_line(colour = "grey90", size = 0.25), 
-                panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
-                panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
-                axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
-                axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
-                aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
-            ))
-        }else{
-            assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-                text = ggplot2::element_text(size = text.size), 
-                plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-                line = ggplot2::element_line(size = 0.5), 
-                legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-                axis.line.y.left = ggplot2::element_line(colour = "black"), 
-                axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
-                axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
-                axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
-                aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
-            ))
-        }
-    }else if(add.check == TRUE & article == FALSE){
-        assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), m.gg <- ggplot2::theme(
-            text = ggplot2::element_text(size = text.size), 
-            plot.title = ggplot2::element_text(size = title.text.size), # stronger than text
-            line = ggplot2::element_line(size = 0.5), 
-            legend.key = ggplot2::element_rect(color = "white", size = 1.5), # size of the frame of the legend
-            panel.background = ggplot2::element_rect(fill = "grey95"), 
-            axis.line.y.left = ggplot2::element_line(colour = "black"), 
-            axis.line.x.bottom = ggplot2::element_line(colour = "black"), 
-            panel.grid.major.x = ggplot2::element_line(colour = "grey85", size = 0.75), 
-            panel.grid.minor.x = ggplot2::element_line(colour = "grey90", size = 0.25), 
-            panel.grid.major.y = ggplot2::element_line(colour = "grey85", size = 0.75), 
-            panel.grid.minor.y = ggplot2::element_line(colour = "grey90", size = 0.25), 
-            strip.background = ggplot2::element_rect(fill = "white", colour = "black"), 
-            axis.text.x = ggplot2::element_text(angle = x.tempo.just$angle, hjust = x.tempo.just$hjust, vjust = x.tempo.just$vjust),
-            axis.text.y = ggplot2::element_text(angle = y.tempo.just$angle, hjust = y.tempo.just$hjust, vjust = y.tempo.just$vjust), 
-            aspect.ratio = if(fix.ratio == TRUE){raster.ratio}else{NULL} # for raster
-            # do not work -> legend.position = "none" # to remove the legend completely: https://www.datanovia.com/en/blog/how-to-remove-legend-from-a-ggplot/
-        ))
-    }
-    # end no need loop part
-    
-    
-    # loop part
-    point.count <- 0
-    line.count <- 0
-    lg.order <- vector(mode = "list", length = 6) # order of the legend
-    lg.order <- lapply(lg.order, as.numeric) # order of the legend
-    lg.color <- vector(mode = "list", length = 6) # color of the legend
-    lg.dot.shape <- vector(mode = "list", length = 6) # etc.
-    lg.dot.size <- vector(mode = "list", length = 6) # etc.
-    lg.dot.size <- lapply(lg.dot.size, as.numeric) # etc.
-    lg.dot.border.size <- vector(mode = "list", length = 6) # etc.
-    lg.dot.border.size <- lapply(lg.dot.border.size, as.numeric) # etc.
-    lg.dot.border.color <- vector(mode = "list", length = 6) # etc.
-    lg.line.size <- vector(mode = "list", length = 6) # etc.
-    lg.line.size <- lapply(lg.line.size, as.numeric) # etc.
-    lg.line.type <- vector(mode = "list", length = 6) # etc.
-    lg.alpha <- vector(mode = "list", length = 6) # etc.
-    lg.alpha <- lapply(lg.alpha, as.numeric) # etc.
-    for(i1 in 1:length(data1)){
-        if(geom[[i1]] == "geom_point"){
-            point.count <- point.count + 1
-            if(point.count== 1L){
-                fin.lg.disp[[1]] <- legend.disp[[point.count + line.count]]
-                lg.order[[1]] <- point.count + line.count
-                lg.color[[1]] <- color[[i1]] # if color == NULL -> NULL
-                lg.dot.shape[[1]] <- dot.shape[[i1]]
-                lg.dot.size[[1]] <- dot.size[[i1]]
-                lg.dot.border.size[[1]] <- dot.border.size[[i1]]
-                lg.dot.border.color[[1]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
-                if(plot == TRUE & fin.lg.disp[[1]] == TRUE & dot.shape[[1]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[1]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[1]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], fill = categ[[i1]]), shape = dot.shape[[i1]], size = dot.size[[i1]], stroke = dot.border.size[[i1]], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = if(i5== 1L){TRUE}else{FALSE})) # WARNING: a single color allowed for color argument outside aesthetic, but here a single color for border --> loop could be inactivated but kept for commodity # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_fill_manual(name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = as.character(color[[i1]]), breaks = class.categ)) # values are the values of fill, breaks reorder the classes according to class.categ in the legend, order argument of guide_legend determines the order of the different aesthetics in the legend (not order of classes). See guide_legend settings of scale_..._manual below
-            }
-            if(point.count== 2L){
-                fin.lg.disp[[2]] <- legend.disp[[point.count + line.count]]
-                lg.order[[2]] <- point.count + line.count
-                lg.color[[2]] <- color[[i1]] # if color == NULL -> NULL
-                lg.dot.shape[[2]] <- dot.shape[[i1]]
-                lg.dot.size[[2]] <- dot.size[[i1]]
-                lg.dot.border.size[[2]] <- dot.border.size[[i1]]
-                lg.dot.border.color[[2]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
-                if(plot == TRUE & fin.lg.disp[[2]] == TRUE & dot.shape[[2]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[2]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[2]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], shape = categ[[i1]]), size = dot.size[[i1]], stroke = dot.border.size[[i1]], fill = color[[i1]][i5], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = FALSE)) # WARNING: a single color allowed for fill argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_shape_manual(name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(dot.shape[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of shape, breaks reorder the classes according to class.categ in the legend. See guide_legend settings of scale_..._manual below
-                
-            }
-            if(point.count== 3L){
-                fin.lg.disp[[3]] <- legend.disp[[point.count + line.count]]
-                lg.order[[3]] <- point.count + line.count
-                lg.color[[3]] <- color[[i1]] # if color == NULL -> NULL
-                lg.dot.shape[[3]] <- dot.shape[[i1]]
-                lg.dot.size[[3]] <- dot.size[[i1]]
-                lg.dot.border.size[[3]] <- dot.border.size[[i1]]
-                lg.dot.border.color[[3]] <- dot.border.color[[i1]] # if dot.border.color == NULL -> NULL
-                if(plot == TRUE & fin.lg.disp[[3]] == TRUE & dot.shape[[3]] %in% 0:14 & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE DOTS (DOT LAYER NUMBER ", point.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[3]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[3]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = scatter.kind[[i1]]))(data = tempo.data.frame, mapping = ggplot2::aes_string(x = x[[i1]], y = y[[i1]], stroke = categ[[i1]]), shape = dot.shape[[i1]], size = dot.size[[i1]], fill = color[[i1]][i5], stroke = dot.border.size[[i1]], color = if(dot.shape[[i1]] %in% 21:24 & ! is.null(dot.border.color)){dot.border.color[[i1]]}else{color[[i1]][i5]}, alpha = alpha[[i1]], show.legend = FALSE)) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "stroke", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(dot.border.size[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of stroke, breaks reorder the classes according to class.categ in the legend. See guide_legend settings of scale_..._manual below
-                
-            }
-        }else{
-            line.count <- line.count + 1
-            if(line.count== 1L){
-                fin.lg.disp[[4]] <- legend.disp[[point.count + line.count]]
-                lg.order[[4]] <- point.count + line.count
-                lg.color[[4]] <- color[[i1]] # if color == NULL -> NULL
-                lg.line.size[[4]] <- line.size[[i1]]
-                lg.line.type[[4]] <- line.type[[i1]]
-                if(plot == TRUE & fin.lg.disp[[4]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[4]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[4]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
-                                                                                                                 "(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
-                                                                                                                 x[[i1]], 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
-                                                                                                                 y[[i1]], 
-                                                                                                                 if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
-                                                                                                                 ", linetype = ", 
-                                                                                                                 categ[[i1]], 
-                                                                                                                 "), color = \"", 
-                                                                                                                 color[[i1]][i5], 
-                                                                                                                 "\", size = ", 
-                                                                                                                 line.size[[i1]], 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
-                                                                                                                 ", alpha = ", 
-                                                                                                                 alpha[[i1]], 
-                                                                                                                 ", show.legend = ", 
-                                                                                                                 ifelse(i5== 1L, TRUE, FALSE), 
-                                                                                                                 ")"
-                    )))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "linetype", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(line.type[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, with different values, breaks reorder the classes according to class.categ in the legend
-            }
-            if(line.count== 2L){
-                fin.lg.disp[[5]] <- legend.disp[[point.count + line.count]]
-                lg.order[[5]] <- point.count + line.count
-                lg.color[[5]] <- color[[i1]] # if color == NULL -> NULL
-                lg.line.size[[5]] <- line.size[[i1]]
-                lg.line.type[[5]] <- line.type[[i1]]
-                if(plot == TRUE & fin.lg.disp[[5]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[5]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[5]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
-                                                                                                                 "(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
-                                                                                                                 x[[i1]], 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
-                                                                                                                 y[[i1]], 
-                                                                                                                 if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
-                                                                                                                 ", alpha = ", 
-                                                                                                                 categ[[i1]], 
-                                                                                                                 "), color = \"", 
-                                                                                                                 color[[i1]][i5], 
-                                                                                                                 "\", size = ", 
-                                                                                                                 line.size[[i1]], 
-                                                                                                                 ", linetype = ", 
-                                                                                                                 ifelse(is.numeric(line.type[[i1]]), "", "\""), 
-                                                                                                                 line.type[[i1]], 
-                                                                                                                 ifelse(is.numeric(line.type[[i1]]), "", "\""), 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
-                                                                                                                 ", show.legend = FALSE)"
-                    )))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "alpha", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(alpha[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, with different values, breaks reorder the classes according to class.categ in the legend
-            }
-            if(line.count== 3L){
-                fin.lg.disp[[6]] <- legend.disp[[point.count + line.count]]
-                lg.order[[6]] <- point.count + line.count
-                lg.color[[6]] <- color[[i1]] # if color == NULL -> NULL
-                lg.line.size[[6]] <- line.size[[i1]]
-                lg.line.type[[6]] <- line.type[[i1]]
-                if(plot == TRUE & fin.lg.disp[[6]] == TRUE & ((length(dev.list()) > 0 & names(dev.cur()) == "windows") | (length(dev.list())== 0L & Sys.info()["sysname"] == "Windows"))){ # if any Graph device already open and this device is "windows", or if no Graph device opened yet and we are on windows system -> prevention of alpha legend bug on windows using value 1
-                    warn.count <- warn.count + 1
-                    tempo.warn <- paste0("(", warn.count,") GRAPHIC DEVICE USED ON A WINDOWS SYSTEM ->\nTRANSPARENCY OF THE LINES (LINE LAYER NUMBER ", line.count, ") IS INACTIVATED IN THE LEGEND TO PREVENT A WINDOWS DEPENDENT BUG (SEE https://github.com/tidyverse/ggplot2/issues/2452)\nTO OVERCOME THIS ON WINDOWS, USE ANOTHER DEVICE (pdf() FOR INSTANCE)")
-                    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-                    lg.alpha[[6]] <- 1 # to avoid a bug on windows: if alpha argument is different from 1 for lines (transparency), then lines are not correctly displayed in the legend when using the R GUI (bug https://github.com/tidyverse/ggplot2/issues/2452). No bug when using a pdf
-                }else{
-                    lg.alpha[[6]] <- alpha[[i1]]
-                }
-                class.categ <- levels(factor(data1[[i1]][, categ[[i1]]]))
-                for(i5 in 1:length(color[[i1]])){ # or length(class.categ). It is the same because already checked that lengths are the same
-                    tempo.data.frame <- data1[[i1]][data1[[i1]][, categ[[i1]]] == class.categ[i5], ]
-                    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = paste0("ggplot2::", # no CR here te0("ggpl
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', 'geom_segment', geom[[i1]]), # geom_segment because geom_stick converted to geom_segment for plotting
-                                                                                                                 "(data = tempo.data.frame, mapping = ggplot2::aes(x = ", 
-                                                                                                                 x[[i1]], 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_stick', ", yend = ", ", y = "), 
-                                                                                                                 y[[i1]], 
-                                                                                                                 if(geom[[i1]] == 'geom_stick'){paste0(', xend = ', x[[i1]], ', y = ', ifelse(is.null(geom.stick.base), y.lim[1], geom.stick.base[[i1]]))}, 
-                                                                                                                 ", size = ", 
-                                                                                                                 categ[[i1]], 
-                                                                                                                 "), color = \"", 
-                                                                                                                 color[[i1]][i5], 
-                                                                                                                 "\", linetype = ", 
-                                                                                                                 ifelse(is.numeric(line.type[[i1]]), "", "\""), 
-                                                                                                                 line.type[[i1]], 
-                                                                                                                 ifelse(is.numeric(line.type[[i1]]), "", "\""), 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_path', ', lineend = \"round\"', ''), 
-                                                                                                                 ifelse(geom[[i1]] == 'geom_step', paste0(', direction = \"', geom.step.dir[[i1]], '\"'), ''), 
-                                                                                                                 ", alpha = ", 
-                                                                                                                 alpha[[i1]], 
-                                                                                                                 ", show.legend = FALSE)"
-                    )))) # WARNING: a single color allowed for color argument outside aesthetic, hence the loop # legend.show option do not remove the legend, only the aesthetic of the legend (dot, line, etc.). Used here to avoid multiple layers of legend which corrupt transparency
-                    coord.names <- c(coord.names, paste0(geom[[i1]], ".", class.categ[i5]))
-                }
-                assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_discrete_manual(aesthetics = "size", name = if(is.null(legend.name)){NULL}else{legend.name[[i1]]}, values = rep(line.size[[i1]], length(color[[i1]])), breaks = class.categ)) # values are the values of linetype. 1 means solid. Regarding the alpha bug, I have tried different things without success: alpha in guide alone, in geom alone, in both, breaks reorder the classes according to class.categ in the legend
-            }
-        }
-    }
-    # end loop part
-    
-    
-    
-    
-    # legend display
-    tempo.legend.final <- 'ggplot2::guides(
+# legend display
+tempo.legend.final <- 'ggplot2::guides(
 fill = if(fin.lg.disp[[1]] == TRUE){
 ggplot2::guide_legend(
 order = lg.order[[1]], 
@@ -13506,25 +13517,25 @@ FALSE
 }
 )' # clip = "off" to have secondary ticks outside plot region does not work
 if( ! is.null(legend.width)){
-    if(any(unlist(legend.disp))){ # means some TRUE
-        tempo.graph.info <- suppressMessages(ggplot2::ggplot_build(eval(parse(text = paste0(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + ', tempo.legend.final))))) # will be recovered later again, when ylim will be considered
-        legend.final <- fun_gg_get_legend(ggplot_built = tempo.graph.info, fun.name = function.name) # get legend
-        fin.lg.disp[] <- FALSE # remove all the legends. Must be done even if fin.lg.disp is not appearing in the code thenafter. Otherwise twice the legend
-        if(is.null(legend.final) & plot == TRUE){ # even if any(unlist(legend.disp)) is TRUE
-            legend.final <- fun_gg_empty_graph() # empty graph instead of legend
-            warn.count <- warn.count + 1
-            tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON-NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON-NULL legend.width ARGUMENT\n")
-            warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-        }
-    }else if(plot == TRUE){ # means all FALSE
-        legend.final <- ggplot2::ggplot()+ggplot2::theme_void() # empty graph instead of legend
-        warn.count <- warn.count + 1
-        tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON-NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON-NULL legend.width ARGUMENT\n")
-        warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
-    }
+if(any(unlist(legend.disp))){ # means some TRUE
+tempo.graph.info <- suppressMessages(ggplot2::ggplot_build(eval(parse(text = paste0(paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + "), ' + ', tempo.legend.final))))) # will be recovered later again, when ylim will be considered
+legend.final <- fun_gg_get_legend(ggplot_built = tempo.graph.info, fun.name = function.name) # get legend
+fin.lg.disp[] <- FALSE # remove all the legends. Must be done even if fin.lg.disp is not appearing in the code thenafter. Otherwise twice the legend
+if(is.null(legend.final) & plot == TRUE){ # even if any(unlist(legend.disp)) is TRUE
+legend.final <- fun_gg_empty_graph() # empty graph instead of legend
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON-NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON-NULL legend.width ARGUMENT\n")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
+}else if(plot == TRUE){ # means all FALSE
+legend.final <- ggplot2::ggplot()+ggplot2::theme_void() # empty graph instead of legend
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") LEGEND REQUESTED (NON-NULL categ ARGUMENT OR legend.show ARGUMENT SET TO TRUE)\nBUT IT SEEMS THAT THE PLOT HAS NO LEGEND -> EMPTY LEGEND SPACE CREATED BECAUSE OF THE NON-NULL legend.width ARGUMENT\n")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+}
 }
 if( ! any(unlist(legend.disp))){
-    fin.lg.disp[] <- FALSE # remove all the legends. Must be done even if fin.lg.disp is not appearing in the code thenafter. Otherwise twice the legend
+fin.lg.disp[] <- FALSE # remove all the legends. Must be done even if fin.lg.disp is not appearing in the code thenafter. Otherwise twice the legend
 }
 assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(text = tempo.legend.final)))
 # end legend display
@@ -13537,135 +13548,135 @@ assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), eval(parse(t
 tempo.coord <- suppressMessages(ggplot2::ggplot_build(eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ", ' + ggplot2::scale_x_continuous(expand = c(0, 0), limits = sort(x.lim), oob = scales::rescale_none) + ggplot2::scale_y_continuous(expand = c(0, 0), limits = sort(y.lim), oob = scales::rescale_none)'))))$layout$panel_params[[1]]) # here I do not need the x-axis and y-axis orientation, I just need the number of main ticks
 # x.second.tick.positions # coordinates of secondary ticks (only if x.second.tick.nb argument is non-null or if x.log argument is different from "no")
 if(x.log != "no"){ # integer main ticks for log2 and log10
-    tempo.scale <- (as.integer(min(x.lim, na.rm = TRUE)) - 1):(as.integer(max(x.lim, na.rm = TRUE)) + 1)
-}else{
-    tempo <- if(is.null(attributes(tempo.coord$x$breaks))){tempo.coord$x$breaks}else{unlist(attributes(tempo.coord$x$breaks))}
-    if(all(is.na(tempo))){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$x$breaks")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    if(length(unique(x.lim)) <= 1){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nIT SEEMS THAT X-AXIS VALUES HAVE A NULL RANGE: ", paste(x.lim, collapse = " "), "\nPLEASE, USE THE x.lim ARGUMENT WITH 2 DIFFERENT VALUES TO SOLVE THIS")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }else{
-        tempo.scale <- fun_scale(lim = x.lim, n = ifelse(is.null(x.tick.nb), length(tempo[ ! is.na(tempo)]), x.tick.nb)) # in ggplot 3.3.0, tempo.coord$x.major_source replaced by tempo.coord$x$breaks. If fact: n = ifelse(is.null(x.tick.nb), length(tempo[ ! is.na(tempo)]), x.tick.nb)) replaced by n = ifelse(is.null(x.tick.nb), 4, x.tick.nb))
-    }
+tempo.scale <- (as.integer(min(x.lim, na.rm = TRUE)) - 1):(as.integer(max(x.lim, na.rm = TRUE)) + 1)
+}else{
+tempo <- if(is.null(attributes(tempo.coord$x$breaks))){tempo.coord$x$breaks}else{unlist(attributes(tempo.coord$x$breaks))}
+if(all(is.na(tempo))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$x$breaks")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(length(unique(x.lim)) <= 1){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nIT SEEMS THAT X-AXIS VALUES HAVE A NULL RANGE: ", paste(x.lim, collapse = " "), "\nPLEASE, USE THE x.lim ARGUMENT WITH 2 DIFFERENT VALUES TO SOLVE THIS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+tempo.scale <- fun_scale(lim = x.lim, n = ifelse(is.null(x.tick.nb), length(tempo[ ! is.na(tempo)]), x.tick.nb)) # in ggplot 3.3.0, tempo.coord$x.major_source replaced by tempo.coord$x$breaks. If fact: n = ifelse(is.null(x.tick.nb), length(tempo[ ! is.na(tempo)]), x.tick.nb)) replaced by n = ifelse(is.null(x.tick.nb), 4, x.tick.nb))
+}
 }
 x.second.tick.values <- NULL
 x.second.tick.pos <- NULL
 if(x.log != "no"){
-    tempo <- fun_inter_ticks(lim = x.lim, log = x.log)
-    x.second.tick.values <- tempo$values
-    x.second.tick.pos <- tempo$coordinates
-    # if(vertical == TRUE){ # do not remove in case the bug is fixed
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
-        geom = "segment", x = x.second.tick.pos, 
-        xend = x.second.tick.pos, 
-        y = if(diff(y.lim) > 0){tempo.coord$y.range[1]}else{tempo.coord$y.range[2]}, 
-        yend = if(diff(y.lim) > 0){tempo.coord$y.range[1] + abs(diff(tempo.coord$y.range)) / 80}else{tempo.coord$y.range[2] - abs(diff(tempo.coord$y.range)) / 80}
-    ))
-    # }else{ # not working because of the ggplot2 bug
-    # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", y = x.second.tick.pos, yend = x.second.tick.pos, x = tempo.coord$x.range[1], xend = tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80))
-    # }
-    coord.names <- c(coord.names, "x.second.tick.positions")
+tempo <- fun_inter_ticks(lim = x.lim, log = x.log)
+x.second.tick.values <- tempo$values
+x.second.tick.pos <- tempo$coordinates
+# if(vertical == TRUE){ # do not remove in case the bug is fixed
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
+geom = "segment", x = x.second.tick.pos, 
+xend = x.second.tick.pos, 
+y = if(diff(y.lim) > 0){tempo.coord$y.range[1]}else{tempo.coord$y.range[2]}, 
+yend = if(diff(y.lim) > 0){tempo.coord$y.range[1] + abs(diff(tempo.coord$y.range)) / 80}else{tempo.coord$y.range[2] - abs(diff(tempo.coord$y.range)) / 80}
+))
+# }else{ # not working because of the ggplot2 bug
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", y = x.second.tick.pos, yend = x.second.tick.pos, x = tempo.coord$x.range[1], xend = tempo.coord$x.range[1] + diff(tempo.coord$x.range) / 80))
+# }
+coord.names <- c(coord.names, "x.second.tick.positions")
 }else if(( ! is.null(x.second.tick.nb)) & x.log == "no"){
-    # if(x.second.tick.nb > 0){ #inactivated because already checked before
-    if(length(tempo.scale) < 2){
-        tempo.cat1 <- c("x.tick.nb", "x.second.tick.nb")
-        tempo.cat2 <- sapply(list(x.tick.nb, x.second.tick.nb), FUN = paste0, collapse = " ")
-        tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE X-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        tempo <- fun_inter_ticks(lim = x.lim, log = x.log, breaks = tempo.scale, n = x.second.tick.nb)
-    }
-    x.second.tick.values <- tempo$values
-    x.second.tick.pos <- tempo$coordinates
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
-        geom = "segment", 
-        x = x.second.tick.pos, 
-        xend = x.second.tick.pos, 
-        y = if(diff(y.lim) > 0){tempo.coord$y.range[1]}else{tempo.coord$y.range[2]}, 
-        yend = if(diff(y.lim) > 0){tempo.coord$y.range[1] + abs(diff(tempo.coord$y.range)) / 80}else{tempo.coord$y.range[2] - abs(diff(tempo.coord$y.range)) / 80}
-    ))
-    coord.names <- c(coord.names, "x.second.tick.positions")
+# if(x.second.tick.nb > 0){ #inactivated because already checked before
+if(length(tempo.scale) < 2){
+tempo.cat1 <- c("x.tick.nb", "x.second.tick.nb")
+tempo.cat2 <- sapply(list(x.tick.nb, x.second.tick.nb), FUN = paste0, collapse = " ")
+tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE X-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+tempo <- fun_inter_ticks(lim = x.lim, log = x.log, breaks = tempo.scale, n = x.second.tick.nb)
+}
+x.second.tick.values <- tempo$values
+x.second.tick.pos <- tempo$coordinates
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
+geom = "segment", 
+x = x.second.tick.pos, 
+xend = x.second.tick.pos, 
+y = if(diff(y.lim) > 0){tempo.coord$y.range[1]}else{tempo.coord$y.range[2]}, 
+yend = if(diff(y.lim) > 0){tempo.coord$y.range[1] + abs(diff(tempo.coord$y.range)) / 80}else{tempo.coord$y.range[2] - abs(diff(tempo.coord$y.range)) / 80}
+))
+coord.names <- c(coord.names, "x.second.tick.positions")
 }
 # for the ggplot2 bug with x.log, this does not work: eval(parse(text = ifelse(vertical == FALSE & x.log == "log10", "ggplot2::scale_x_continuous", "ggplot2::scale_x_continuous")))
 assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_x_continuous(
-    breaks = tempo.scale, 
-    minor_breaks = x.second.tick.pos, 
-    labels = if(x.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(x.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(x.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 10") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, 
-    expand = c(0, 0), # remove space after after axis limits
-    limits = sort(x.lim), # NA indicate that limits must correspond to data limits but xlim() already used
-    oob = scales::rescale_none, 
-    trans = ifelse(diff(x.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_x_reverse() but create the problem of x-axis label disappearance with x.lim decreasing. Thus, do not use. Use xlim() below and after this
+breaks = tempo.scale, 
+minor_breaks = x.second.tick.pos, 
+labels = if(x.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(x.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(x.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 10") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, 
+expand = c(0, 0), # remove space after after axis limits
+limits = sort(x.lim), # NA indicate that limits must correspond to data limits but xlim() already used
+oob = scales::rescale_none, 
+trans = ifelse(diff(x.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_x_reverse() but create the problem of x-axis label disappearance with x.lim decreasing. Thus, do not use. Use xlim() below and after this
 ))
 # end x.second.tick.positions
 # y.second.tick.positions # coordinates of secondary ticks (only if y.second.tick.nb argument is non-null or if y.log argument is different from "no")
 if(y.log != "no"){ # integer main ticks for log2 and log10
-    tempo.scale <- (as.integer(min(y.lim, na.rm = TRUE)) - 1):(as.integer(max(y.lim, na.rm = TRUE)) + 1)
-}else{
-    tempo <- if(is.null(attributes(tempo.coord$y$breaks))){tempo.coord$y$breaks}else{unlist(attributes(tempo.coord$y$breaks))}
-    if(all(is.na(tempo))){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$y$breaks")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }
-    if(length(unique(y.lim)) <= 1){
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nIT SEEMS THAT Y-AXIS VALUES HAVE A NULL RANGE: ", paste(y.lim, collapse = " "), "\nPLEASE, USE THE y.lim ARGUMENT WITH 2 DIFFERENT VALUES TO SOLVE THIS")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }else{
-        tempo.scale <- fun_scale(lim = y.lim, n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks. If fact: n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) replaced by n = ifelse(is.null(y.tick.nb), 4, y.tick.nb))
-    }
+tempo.scale <- (as.integer(min(y.lim, na.rm = TRUE)) - 1):(as.integer(max(y.lim, na.rm = TRUE)) + 1)
+}else{
+tempo <- if(is.null(attributes(tempo.coord$y$breaks))){tempo.coord$y$breaks}else{unlist(attributes(tempo.coord$y$breaks))}
+if(all(is.na(tempo))){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nONLY NA IN tempo.coord$y$breaks")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}
+if(length(unique(y.lim)) <= 1){
+tempo.cat <- paste0("ERROR IN ", function.name, "\nIT SEEMS THAT Y-AXIS VALUES HAVE A NULL RANGE: ", paste(y.lim, collapse = " "), "\nPLEASE, USE THE y.lim ARGUMENT WITH 2 DIFFERENT VALUES TO SOLVE THIS")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+tempo.scale <- fun_scale(lim = y.lim, n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) # in ggplot 3.3.0, tempo.coord$y.major_source replaced by tempo.coord$y$breaks. If fact: n = ifelse(is.null(y.tick.nb), length(tempo[ ! is.na(tempo)]), y.tick.nb)) replaced by n = ifelse(is.null(y.tick.nb), 4, y.tick.nb))
+}
 }
 y.second.tick.values <- NULL
 y.second.tick.pos <- NULL
 if(y.log != "no"){
-    tempo <- fun_inter_ticks(lim = y.lim, log = y.log)
-    y.second.tick.values <- tempo$values
-    y.second.tick.pos <- tempo$coordinates
-    # if(vertical == TRUE){ # do not remove in case the bug is fixed
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
-        geom = "segment", 
-        y = y.second.tick.pos, 
-        yend = y.second.tick.pos, 
-        x = if(diff(x.lim) > 0){tempo.coord$x.range[1]}else{tempo.coord$x.range[2]}, 
-        xend = if(diff(x.lim) > 0){tempo.coord$x.range[1] + abs(diff(tempo.coord$x.range)) / 80}else{tempo.coord$x.range[2] - abs(diff(tempo.coord$x.range)) / 80}
-    ))
-    # }else{ # not working because of the ggplot2 bug
-    # assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", x = y.second.tick.pos, xend = y.second.tick.pos, y = tempo.coord$y.range[1], yend = tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80))
-    # }
-    coord.names <- c(coord.names, "y.second.tick.positions")
+tempo <- fun_inter_ticks(lim = y.lim, log = y.log)
+y.second.tick.values <- tempo$values
+y.second.tick.pos <- tempo$coordinates
+# if(vertical == TRUE){ # do not remove in case the bug is fixed
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
+geom = "segment", 
+y = y.second.tick.pos, 
+yend = y.second.tick.pos, 
+x = if(diff(x.lim) > 0){tempo.coord$x.range[1]}else{tempo.coord$x.range[2]}, 
+xend = if(diff(x.lim) > 0){tempo.coord$x.range[1] + abs(diff(tempo.coord$x.range)) / 80}else{tempo.coord$x.range[2] - abs(diff(tempo.coord$x.range)) / 80}
+))
+# }else{ # not working because of the ggplot2 bug
+# assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(geom = "segment", x = y.second.tick.pos, xend = y.second.tick.pos, y = tempo.coord$y.range[1], yend = tempo.coord$y.range[1] + diff(tempo.coord$y.range) / 80))
+# }
+coord.names <- c(coord.names, "y.second.tick.positions")
 }else if(( ! is.null(y.second.tick.nb)) & y.log == "no"){
-    # if(y.second.tick.nb > 0){ #inactivated because already checked before
-    if(length(tempo.scale) < 2){
-        tempo.cat1 <- c("y.tick.nb", "y.second.tick.nb")
-        tempo.cat2 <- sapply(list(y.tick.nb, y.second.tick.nb), FUN = paste0, collapse = " ")
-        tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
-        tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE Y-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
-    }else{
-        tempo <- fun_inter_ticks(lim = y.lim, log = y.log, breaks = tempo.scale, n = y.second.tick.nb)
-    }
-    y.second.tick.values <- tempo$values
-    y.second.tick.pos <- tempo$coordinates
-    assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
-        geom = "segment", 
-        y = y.second.tick.pos, 
-        yend = y.second.tick.pos, 
-        x = if(diff(x.lim) > 0){tempo.coord$x.range[1]}else{tempo.coord$x.range[2]}, 
-        xend = if(diff(x.lim) > 0){tempo.coord$x.range[1] + abs(diff(tempo.coord$x.range)) / 80}else{tempo.coord$x.range[2] - abs(diff(tempo.coord$x.range)) / 80}
-    ))
-    coord.names <- c(coord.names, "y.second.tick.positions")
+# if(y.second.tick.nb > 0){ #inactivated because already checked before
+if(length(tempo.scale) < 2){
+tempo.cat1 <- c("y.tick.nb", "y.second.tick.nb")
+tempo.cat2 <- sapply(list(y.tick.nb, y.second.tick.nb), FUN = paste0, collapse = " ")
+tempo.sep <- sapply(mapply(" ", max(nchar(tempo.cat1)) - nchar(tempo.cat1) + 3, FUN = rep, SIMPLIFY = FALSE), FUN = paste0, collapse = "")
+tempo.cat <- paste0("ERROR IN ", function.name, "\nTHE NUMBER OF GENERATED TICKS FOR THE Y-AXIS IS NOT CORRECT: ", length(tempo.scale), "\nUSING THESE ARGUMENT SETTINGS (NO DISPLAY MEANS NULL VALUE):\n", paste0(tempo.cat1, tempo.sep, tempo.cat2, collapse = "\n"), "\nPLEASE, TEST OTHER VALUES")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE) # == in stop() to be able to add several messages between ==
+}else{
+tempo <- fun_inter_ticks(lim = y.lim, log = y.log, breaks = tempo.scale, n = y.second.tick.nb)
+}
+y.second.tick.values <- tempo$values
+y.second.tick.pos <- tempo$coordinates
+assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::annotate(
+geom = "segment", 
+y = y.second.tick.pos, 
+yend = y.second.tick.pos, 
+x = if(diff(x.lim) > 0){tempo.coord$x.range[1]}else{tempo.coord$x.range[2]}, 
+xend = if(diff(x.lim) > 0){tempo.coord$x.range[1] + abs(diff(tempo.coord$x.range)) / 80}else{tempo.coord$x.range[2] - abs(diff(tempo.coord$x.range)) / 80}
+))
+coord.names <- c(coord.names, "y.second.tick.positions")
 }
 # for the ggplot2 bug with y.log, this does not work: eval(parse(text = ifelse(vertical == FALSE & y.log == "log10", "ggplot2::scale_x_continuous", "ggplot2::scale_y_continuous")))
 assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::scale_y_continuous(
-    breaks = tempo.scale, 
-    minor_breaks = y.second.tick.pos, 
-    labels = if(y.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(y.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(y.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 10") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, 
-    expand = c(0, 0), # remove space after axis limits
-    limits = sort(y.lim), # NA indicate that limits must correspond to data limits but ylim() already used
-    oob = scales::rescale_none, 
-    trans = ifelse(diff(y.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_y_reverse() but create the problem of y-axis label disappearance with y.lim decreasing. Thus, do not use. Use ylim() below and after this
+breaks = tempo.scale, 
+minor_breaks = y.second.tick.pos, 
+labels = if(y.log == "log10"){scales::trans_format("identity", scales::math_format(10^.x))}else if(y.log == "log2"){scales::trans_format("identity", scales::math_format(2^.x))}else if(y.log == "no"){ggplot2::waiver()}else{tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, "\nCODE INCONSISTENCY 10") ; stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)}, 
+expand = c(0, 0), # remove space after axis limits
+limits = sort(y.lim), # NA indicate that limits must correspond to data limits but ylim() already used
+oob = scales::rescale_none, 
+trans = ifelse(diff(y.lim) < 0, "reverse", "identity") # equivalent to ggplot2::scale_y_reverse() but create the problem of y-axis label disappearance with y.lim decreasing. Thus, do not use. Use ylim() below and after this
 ))
 # end y.second.tick.positions
 assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coord_cartesian(xlim = x.lim, ylim = y.lim)) # clip = "off" to have secondary ticks outside plot region. The problem is that points out of bounds are also drawn outside the plot region. Thus, I cannot use it # at that stage, x.lim and y.lim not NULL anymore
@@ -13678,15 +13689,15 @@ assign(paste0(tempo.gg.name, tempo.gg.count <- tempo.gg.count + 1), ggplot2::coo
 fin.plot <- eval(parse(text = paste(paste0(tempo.gg.name, 1:tempo.gg.count), collapse = " + ")))
 grob.save <- NULL
 if(plot == TRUE){
-    if( ! is.null(legend.width)){ # any(unlist(legend.disp)) == TRUE removed to have empty legend space # not & any(unlist(fin.lg.disp)) == TRUE here because converted to FALSE
-        grob.save <- suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
-    }else{
-        grob.save <- suppressMessages(suppressWarnings(print(fin.plot)))
-    }
+if( ! is.null(legend.width)){ # any(unlist(legend.disp)) == TRUE removed to have empty legend space # not & any(unlist(fin.lg.disp)) == TRUE here because converted to FALSE
+grob.save <- suppressMessages(suppressWarnings(gridExtra::grid.arrange(fin.plot, legend.final, ncol=2, widths=c(1, legend.width))))
+}else{
+grob.save <- suppressMessages(suppressWarnings(print(fin.plot)))
+}
 }else{
-    warn.count <- warn.count + 1
-    tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
-    warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
+warn.count <- warn.count + 1
+tempo.warn <- paste0("(", warn.count,") PLOT NOT SHOWN AS REQUESTED")
+warn <- paste0(ifelse(is.null(warn), tempo.warn, paste0(warn, "\n\n", tempo.warn)))
 }
 # end drawing
 
@@ -13694,49 +13705,49 @@ if(plot == TRUE){
 
 # output
 if(warn.print == TRUE & ! is.null(warn)){
-    on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
+on.exit(warning(paste0("FROM ", function.name, ":\n\n", warn), call. = FALSE))
 }
 on.exit(exp = options(warning.length = ini.warning.length), add = TRUE)
 if(return == TRUE){
-    output <- suppressMessages(ggplot2::ggplot_build(fin.plot))
-    # output$data <- output$data[-1] # yes for boxplot but not for scatter # remove the first data because corresponds to the initial empty boxplot
-    if(length(output$data) != length(coord.names)){
-        tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, ": length(output$data) AND length(coord.names) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
-        stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
-    }else{
-        names(output$data) <- coord.names
-    }
-    if(is.null(unlist(removed.row.nb))){
-        removed.row.nb <- NULL
-        removed.rows <- NULL
-    }else{
-        for(i3 in 1:length(data1)){
-            if( ! is.null(removed.row.nb[[i3]])){
-                removed.row.nb[[i3]] <- sort(removed.row.nb[[i3]])
-                removed.rows[[i3]] <- data1.ini[[i3]][removed.row.nb[[i3]], ]
-            }
-        }
-    }
-    tempo <- output$layout$panel_params[[1]]
-    output <- list(
-        data = data1, 
-        removed.row.nb = removed.row.nb, 
-        removed.rows = removed.rows, 
-        plot = c(output$data, x.second.tick.values = list(x.second.tick.values), y.second.tick.values = list(y.second.tick.values)), 
-        panel = facet.categ, 
-        axes = list(
-            x.range = tempo$x.range, 
-            x.labels = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{tempo$x$scale$get_labels()}, # is.null(attributes(tempo$x$breaks)) test if it is number (TRUE) or character (FALSE)
-            x.positions = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{unlist(attributes(tempo$x$breaks))}, 
-            y.range = tempo$y.range, 
-            y.labels = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{tempo$y$scale$get_labels()}, 
-            y.positions = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{unlist(attributes(tempo$y$breaks))}
-        ), 
-        warn = paste0("\n", warn, "\n\n"), 
-        ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL}, # fin.plot plots the graph if return == TRUE
-        gtable = if(return.gtable == TRUE){grob.save}else{NULL} #
-    )
-    return(output) # this plots the graph if return.ggplot is TRUE and if no assignment
+output <- suppressMessages(ggplot2::ggplot_build(fin.plot))
+# output$data <- output$data[-1] # yes for boxplot but not for scatter # remove the first data because corresponds to the initial empty boxplot
+if(length(output$data) != length(coord.names)){
+tempo.cat <- paste0("INTERNAL CODE ERROR IN ", function.name, ": length(output$data) AND length(coord.names) MUST BE IDENTICAL. CODE HAS TO BE MODIFIED")
+stop(paste0("\n\n================\n\n", tempo.cat, "\n\n================\n\n", ifelse(is.null(warn), "", paste0("IN ADDITION\nWARNING", ifelse(warn.count > 1, "S", ""), ":\n\n", warn))), call. = FALSE)
+}else{
+names(output$data) <- coord.names
+}
+if(is.null(unlist(removed.row.nb))){
+removed.row.nb <- NULL
+removed.rows <- NULL
+}else{
+for(i3 in 1:length(data1)){
+if( ! is.null(removed.row.nb[[i3]])){
+removed.row.nb[[i3]] <- sort(removed.row.nb[[i3]])
+removed.rows[[i3]] <- data1.ini[[i3]][removed.row.nb[[i3]], ]
+}
+}
+}
+tempo <- output$layout$panel_params[[1]]
+output <- list(
+data = data1, 
+removed.row.nb = removed.row.nb, 
+removed.rows = removed.rows, 
+plot = c(output$data, x.second.tick.values = list(x.second.tick.values), y.second.tick.values = list(y.second.tick.values)), 
+panel = facet.categ, 
+axes = list(
+x.range = tempo$x.range, 
+x.labels = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{tempo$x$scale$get_labels()}, # is.null(attributes(tempo$x$breaks)) test if it is number (TRUE) or character (FALSE)
+x.positions = if(is.null(attributes(tempo$x$breaks))){tempo$x$breaks}else{unlist(attributes(tempo$x$breaks))}, 
+y.range = tempo$y.range, 
+y.labels = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{tempo$y$scale$get_labels()}, 
+y.positions = if(is.null(attributes(tempo$y$breaks))){tempo$y$breaks}else{unlist(attributes(tempo$y$breaks))}
+), 
+warn = paste0("\n", warn, "\n\n"), 
+ggplot = if(return.ggplot == TRUE){fin.plot}else{NULL}, # fin.plot plots the graph if return == TRUE
+gtable = if(return.gtable == TRUE){grob.save}else{NULL} #
+)
+return(output) # this plots the graph if return.ggplot is TRUE and if no assignment
 }
 # end output
 # end main code
@@ -13744,5 +13755,3 @@ if(return == TRUE){
 
 
 
-
-
diff --git a/cute_little_R_functions.docx b/cute_little_R_functions.docx
index 5bb05e5ba1bb63ae34118a6f16aec59f80ed3253..df908e58e29fc5dc6719093ced789e1c0c0affec 100755
GIT binary patch
delta 425774
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%0DbG
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%0D2^{+<oS
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

delta 425310
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%0D-W&50`Y;32yHHiu7(aQkggQd^<@<u5TV
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%0AH=<n6{aYfjwr=&yt
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

-- 
GitLab