Spaces:
Sleeping
Sleeping
| # Rôle du fichier: ui.R porte une partie du pipeline d'analyse IRaMuTeQ-lite. | |
| # ui.R | |
| library(shiny) | |
| library(bslib) | |
| library(htmltools) | |
| if (!exists("ui_options_iramuteq", mode = "function", inherits = TRUE)) { | |
| app_dir <- tryCatch(shiny::getShinyOption("appDir"), error = function(e) NULL) | |
| if (is.null(app_dir) || !nzchar(app_dir)) app_dir <- getwd() | |
| chemin_options_iramuteq <- file.path(app_dir, "iramuteqlite", "ui_options_iramuteq.R") | |
| if (file.exists(chemin_options_iramuteq)) { | |
| source(chemin_options_iramuteq, encoding = "UTF-8", local = TRUE) | |
| } | |
| } | |
| if (!exists("ui_resultats_chd_iramuteq", mode = "function", inherits = TRUE)) { | |
| app_dir <- tryCatch(shiny::getShinyOption("appDir"), error = function(e) NULL) | |
| if (is.null(app_dir) || !nzchar(app_dir)) app_dir <- getwd() | |
| chemin_affichage_iramuteq <- file.path(app_dir, "iramuteqlite", "affichage_iramuteq.R") | |
| if (file.exists(chemin_affichage_iramuteq)) { | |
| source(chemin_affichage_iramuteq, encoding = "UTF-8", local = TRUE) | |
| } | |
| } | |
| if (!exists("ui_explorateur_iramuteq", mode = "function", inherits = TRUE)) { | |
| app_dir <- tryCatch(shiny::getShinyOption("appDir"), error = function(e) NULL) | |
| if (is.null(app_dir) || !nzchar(app_dir)) app_dir <- getwd() | |
| chemin_explorateur_iramuteq <- file.path(app_dir, "iramuteqlite", "ui_explorateur_iramuteq.R") | |
| if (file.exists(chemin_explorateur_iramuteq)) { | |
| source(chemin_explorateur_iramuteq, encoding = "UTF-8", local = TRUE) | |
| } | |
| } | |
| if (!exists("ui_aide_huggingface", mode = "function")) { | |
| if (file.exists("help/help.md")) { | |
| ui_aide_huggingface <- function() { | |
| tagList( | |
| tags$h2("Aide"), | |
| includeMarkdown("help/help.md") | |
| ) | |
| } | |
| } else { | |
| ui_aide_huggingface <- function() { | |
| tagList( | |
| tags$h2("Aide"), | |
| tags$p("Le fichier help/help.md est introuvable. Vérifie le dossier d'aide du projet.") | |
| ) | |
| } | |
| } | |
| } | |
| if (!exists("ui_aide_morpho", mode = "function")) { | |
| if (file.exists("help/pos_lexique.md")) { | |
| ui_aide_morpho <- function() { | |
| tagList( | |
| tags$h2("Aide morpho"), | |
| includeMarkdown("help/pos_lexique.md") | |
| ) | |
| } | |
| } else { | |
| ui_aide_morpho <- function() { | |
| tagList( | |
| tags$h2("Aide morpho"), | |
| tags$p("Le fichier help/pos_lexique.md est introuvable. Vérifie le dossier d'aide du projet.") | |
| ) | |
| } | |
| } | |
| } | |
| ui_form_parametres_analyse <- function() { | |
| lexique_path <- file.path(getwd(), "dictionnaires", "lexique_fr.csv") | |
| morpho_choices <- c( | |
| "NOM", "NOM_SUP", "VER", "VER_SUP", "AUX", | |
| "ADJ", "ADJ_SUP", "ADJ_DEM", "ADJ_IND", "ADJ_INT", "ADJ_NUM", "ADJ_POS", | |
| "ADV", "ADV_SUP", "PRE", "CON", "ONO", | |
| "PRO_PER", "PRO_POS", "PRO_DEM", "PRO_IND", "PRO_REL", | |
| "ART_DEF", "ART_IND" | |
| ) | |
| if (file.exists(lexique_path)) { | |
| lexique_df <- tryCatch( | |
| utils::read.csv2(lexique_path, stringsAsFactors = FALSE), | |
| error = function(e) NULL | |
| ) | |
| if (is.data.frame(lexique_df) && "c_morpho" %in% names(lexique_df)) { | |
| morpho_from_lexique <- unique(toupper(trimws(as.character(lexique_df$c_morpho)))) | |
| morpho_from_lexique <- morpho_from_lexique[nzchar(morpho_from_lexique)] | |
| if (length(morpho_from_lexique) > 0) { | |
| morpho_choices <- sort(unique(morpho_from_lexique)) | |
| } | |
| } | |
| } | |
| morpho_choices_labels <- stats::setNames(morpho_choices, morpho_choices) | |
| if ("VER_SUP" %in% names(morpho_choices_labels)) { | |
| morpho_choices_labels[["VER_SUP"]] <- "VER_SUP (verbe supplémentaire)" | |
| } | |
| tagList( | |
| radioButtons( | |
| "modele_chd", | |
| "Méthode Iramuteq-like", | |
| choices = c("IRaMuTeQ-lite" = "iramuteq"), | |
| selected = "iramuteq", | |
| inline = FALSE | |
| ), | |
| tags$div(class = "sidebar-section-title", "Paramètres généraux CHD"), | |
| numericInput("segment_size", "segment_size", value = 40, min = 5, step = 1), | |
| numericInput("min_docfreq", "Fréquence minimale des termes (min_docfreq)", value = 3, min = 1, step = 1), | |
| numericInput("max_p", "max_p (p-value)", value = 0.05, min = 0, max = 1, step = 0.01), | |
| checkboxInput("filtrer_affichage_pvalue", "Filtrer l'affichage des résultats par p-value (p ≤ max_p)", value = TRUE), | |
| conditionalPanel( | |
| condition = "input.modele_chd == 'iramuteq'", | |
| ui_options_iramuteq() | |
| ), | |
| tags$div(class = "sidebar-section-title", "Dictionnaire"), | |
| radioButtons( | |
| "source_dictionnaire", | |
| "Source de lemmatisation", | |
| choices = c("Lexique (fr)" = "lexique_fr"), | |
| selected = "lexique_fr", | |
| inline = FALSE | |
| ), | |
| conditionalPanel( | |
| condition = "input.source_dictionnaire == 'lexique_fr'", | |
| checkboxInput("lexique_utiliser_lemmes", "Lemmatisation via les lemmes de lexique_fr (forme → c_lemme)", value = TRUE) | |
| ), | |
| checkboxInput("expression_utiliser_dictionnaire", "Utiliser le dictionnaire d'expression (dic_mot → dic_norm)", value = FALSE), | |
| tags$div(class = "sidebar-section-title", "Nettoyage"), | |
| checkboxInput("nettoyage_caracteres", "Nettoyage caractères (regex)", value = FALSE), | |
| tags$p( | |
| "[^a-zA-Z0-9àÀâÂäÄáÁåÅãéÉèÈêÊëËìÌîÎïÏíÍóÓòÒôÔöÖõÕøØùÙûÛüÜúÚçÇßœŒ’ñÑ\\.:,;!\\?']", | |
| style = "color: #c00; font-size: 0.9em; margin-top: 4px; margin-bottom: 8px;" | |
| ), | |
| tags$p( | |
| "Les caractères présents dans la liste entre crochets sont conservés ; tous les autres (ex. @ # & / emoji) sont remplacés par des espaces.", | |
| style = "color: #c00; font-size: 0.9em; margin-top: 4px; margin-bottom: 8px;" | |
| ), | |
| checkboxInput("supprimer_ponctuation", "Supprimer la ponctuation", value = FALSE), | |
| tags$p( | |
| "Supprime la ponctuation à la tokenisation quanteda (remove_punct), par ex. . , ; : ! ? ' ’ \" - ( ) [ ] …", | |
| style = "color: #c00; font-size: 0.9em; margin-top: 4px; margin-bottom: 8px;" | |
| ), | |
| checkboxInput("supprimer_chiffres", "Supprimer les chiffres (0-9)", value = FALSE), | |
| checkboxInput("supprimer_apostrophes", "Traiter les élisions FR (c'est→est, m'écrire→écrire)", value = FALSE), | |
| checkboxInput("remplacer_tirets_espaces", "Remplacer les tirets (-) par des espaces", value = FALSE), | |
| checkboxInput("retirer_stopwords", "Retirer les stopwords (liste française quanteda)", value = FALSE), | |
| checkboxInput("filtrage_morpho", "Filtrage morphosyntaxique", value = FALSE), | |
| conditionalPanel( | |
| condition = "input.filtrage_morpho == true && input.source_dictionnaire == 'lexique_fr'", | |
| selectizeInput( | |
| "pos_lexique_a_conserver", | |
| "Catégories c_morpho à conserver (lexique_fr)", | |
| choices = morpho_choices_labels, | |
| selected = c("NOM", "VER", "ADJ"), | |
| multiple = TRUE, | |
| options = list(plugins = list("remove_button")) | |
| ) | |
| ), | |
| tags$div(class = "sidebar-section-title", "Paramètres AFC"), | |
| checkboxInput("afc_reduire_chevauchement", "Réduire les chevauchements des mots (AFC)", value = FALSE), | |
| radioButtons( | |
| "afc_taille_mots", | |
| "Taille des mots (AFC termes)", | |
| choices = c("Fréquence" = "frequency", "Chi2" = "chi2"), | |
| selected = "frequency", | |
| inline = FALSE | |
| ), | |
| numericInput("top_n", "Top N mots par classe (nuages)", value = 20, min = 5, step = 1) | |
| ) | |
| } | |
| if (!exists("REGEX_CARACTERES_A_SUPPRIMER", inherits = TRUE)) { | |
| app_dir <- tryCatch(shiny::getShinyOption("appDir"), error = function(e) NULL) | |
| if (is.null(app_dir) || !nzchar(app_dir)) app_dir <- getwd() | |
| chemin_nettoyage <- file.path(app_dir, "iramuteqlite", "nettoyage_iramuteq.R") | |
| if (file.exists(chemin_nettoyage)) { | |
| source(chemin_nettoyage, encoding = "UTF-8", local = TRUE) | |
| } | |
| } | |
| if (!exists("REGEX_CARACTERES_A_SUPPRIMER", inherits = TRUE)) { | |
| REGEX_CARACTERES_AUTORISES <- "a-zA-Z0-9àÀâÂäÄáÁåÅãéÉèÈêÊëËìÌîÎïÏíÍóÓòÒôÔöÖõÕøØùÙûÛüÜúÚçÇßœŒ’ñÑ\\.:,;!\\?'" | |
| REGEX_CARACTERES_A_SUPPRIMER <- paste0("[^", REGEX_CARACTERES_AUTORISES, "]") | |
| } | |
| ui <- page_navbar( | |
| id = "nav_principal", | |
| title = tags$div( | |
| style = "color: #ffffff;", | |
| tags$div(style = "font-weight: 700;", "IRaMuTeQ-Lite"), | |
| tags$small( | |
| style = "display:block; font-size: 0.75rem; line-height: 1.35; font-weight: 400; color: #ffffff; margin-top: 2px;", | |
| "Tentative de reproduction de la CHD du logiciel IRaMuTeQ (IRaMuTeQ - Pierre Ratinaud - LERASS)", | |
| tags$br(), | |
| "Pour d'autres scripts/appli, vous pouvez consulter mon site : www.codeandcortex.fr", | |
| tags$br(), | |
| "version beta 0.1 - 11-03-2026" | |
| ) | |
| ), | |
| theme = bs_theme(version = 5, bootswatch = "flatly"), | |
| fillable = FALSE, | |
| sidebar = sidebar( | |
| width = 320, | |
| open = "always", | |
| title = "Fichier", | |
| actionButton("menu_importer_fichier_sidebar", "Importer le fichier texte", class = "btn-primary"), | |
| tags$div(style = "margin-top: 10px;"), | |
| tags$strong("Nom du fichier :"), | |
| tags$div(textOutput("nom_fichier_selectionne"), style = "margin-bottom: 12px;"), | |
| downloadButton("dl_zip", "Télécharger les résultats") | |
| ), | |
| tags$head( | |
| tags$style(HTML(" | |
| #shiny-modal .modal-dialog { max-width: 760px; margin-top: 6vh; } | |
| #shiny-modal .modal-body { max-height: 70vh; overflow-y: auto; } | |
| .sidebar-section-title { font-weight:700; color:#1e5aa8; margin-top:10px; } | |
| .navbar .container-fluid { display: flex; flex-direction: column; align-items: flex-start; } | |
| .navbar .navbar-brand { color: #ffffff !important; margin-right: 0; white-space: normal; } | |
| .navbar .navbar-brand small { color: #ffffff !important; } | |
| .navbar .navbar-nav { margin-top: 0.5rem; } | |
| ")) | |
| ), | |
| nav_panel( | |
| "Analyse", | |
| value = "analyse", | |
| fluidRow( | |
| column( | |
| width = 12, | |
| actionButton("ouvrir_parametres", "Paramétrer l'analyse", class = "btn-secondary"), | |
| tags$br(), tags$br(), | |
| tags$h3("Statut"), textOutput("statut"), | |
| tags$h3("Journal"), tags$pre(style = "white-space: pre-wrap;", textOutput("logs")), | |
| tags$h3("Analyse du corpus"), uiOutput("ui_table_stats_corpus"), | |
| tags$div(style = "width: 600px;", plotOutput("plot_stats_zipf", height = "600px", width = "600px")), | |
| tags$h3("Répartition des classes"), tableOutput("table_classes") | |
| ) | |
| ) | |
| ), | |
| nav_panel("Corpus", value = "corpus", tags$h3("Corpus importé"), uiOutput("ui_corpus_preview")), | |
| nav_panel("Résultats CHD", value = "resultats_chd", ui_resultats_chd_iramuteq()), | |
| nav_panel( | |
| "AFC", value = "afc", | |
| tags$h3("AFC"), uiOutput("ui_afc_statut"), uiOutput("ui_afc_erreurs"), | |
| tags$h4("AFC des classes"), plotOutput("plot_afc_classes", height = "620px"), | |
| tags$h4("AFC des termes"), | |
| tags$div(style = "display:flex; gap:8px; align-items:center; margin-bottom:8px;", | |
| actionButton("afc_zoom_in", "Zoom +"), | |
| actionButton("afc_zoom_out", "Zoom -"), | |
| actionButton("afc_zoom_reset", "Réinitialiser le zoom AFC termes"), | |
| tags$small("Astuce: cliquer-glisser sur le graphique pour zoomer.") | |
| ), | |
| plotOutput("plot_afc", height = "720px", brush = brushOpts(id = "afc_brush", resetOnNew = TRUE)), | |
| tags$h4("Table des mots projetés"), uiOutput("ui_table_afc_mots_par_classe"), | |
| tags$h4("AFC des variables étoilées"), plotOutput("plot_afc_vars", height = "720px"), | |
| tags$h4("Table des modalités projetées"), tableOutput("table_afc_vars"), | |
| tags$h4("Valeurs propres"), tableOutput("table_afc_eig") | |
| ), | |
| nav_panel("Aide", value = "aide", ui_aide_huggingface()), | |
| nav_panel("Aide morpho", value = "aide_morpho", ui_aide_morpho()) | |
| ) |