Statistics
| Revision:

root / tmp / org.txm.analec.rcp / src / org / txm / macro / urs / edit / Frpos2CattexMacro.groovy @ 1217

History | View | Annotate | Download (10.7 kB)

1
// @author Matthieu Quignard
2
// Date : 04 Mai 2017
3

    
4
/*
5
Définit la catégorie grammaticale des mentions d'après le champ `frpos'
6
(tagset de TreeTagger). 
7

8
La liste des catégories grammaticales est celle de CATTEX2009
9
-- Groupes nominaux :
10
        GN.NAM (noms propres) : Henri II
11
        GN.DEF (définis) : Le roi, du roi
12
        GN.IND (indéfinis) : Un roi
13
        GN.POS (possessifs) : [Mon roi]
14
        GN.DEM (demonstratif) : Ce roi
15
        GN.NUM (numéraux) : Deux rois
16
        GN.CHECK (GN indéterminés)
17
-- Déterminants
18
        DET.POS (possessifs) : [mon] roi
19
-- Pronoms
20
        PRO.PER (personnels) : je, moi, me, on, il, etc.
21
        PRO.ADV (adverbiaux) : y, en
22
        PRO.IND (indéfinis) : tout, tous, certains, plusieurs, etc.
23
        PRO.DEM (demonstratifs) : ceci, cela, ce, ça...
24
        PRO.POS (possessifs) : le mien, les nôtres...
25
        PRO.NUM (cardinaux, ordinaux) : les deux...
26
        PRO.REL (relatifs) : qui, que, quoi, duquel, etc.
27
        PRO.INT (interrogatifs)
28
        PRO.CHECK (pronoms indéterminés)
29
-- Sujet Zéro : verbes conjugués, éventuellement pronominal
30

31
-- ERREUR : erreur (a priori) de mention
32

33
        
34
*/
35

    
36
package org.txm.macro.urs.edit
37

    
38
import org.apache.commons.lang.*
39
import org.kohsuke.args4j.*
40
import groovy.transform.*
41
import org.txm.*
42
import org.txm.rcp.swt.widget.parameters.*
43
import org.txm.annotation.urs.*
44
import org.txm.searchengine.cqp.*
45
import org.txm.searchengine.cqp.corpus.*
46
import visuAnalec.Message.*
47
import visuAnalec.donnees.*
48
import visuAnalec.elements.*
49
import visuAnalec.vue.*
50

    
51
// Propriété donnant le lemme
52
def lemmaProperty = "frlemma"
53

    
54
/*
55
   TODO : TreeTagger fait un mauvais étiquetage des premiers mots de la phrase.
56
   La majuscule lui fait croire qu'il s'agit d'un nom propre.
57
   Vérifier que ce mot n'est pas en fait un pronom en testant sa présence dans une des listes de formes particulières 
58
*/
59

    
60

    
61
/**
62
  * Liste de formes utile à la catégorisation des mentions
63
  * TreeTagger n'est pas forcément très performant sur des états plus anciens de la langue
64
***/  
65

    
66
formesArticlesDéfinis = ["le", "la", "les", "l'", "au", "aux", "du", "des"]
67
formesArticlesIndéfinis = ["un", "une", "des"]
68
formesDéterminantsPossessifs = ["ma", "ta", "sa", "mon", "ton", "son", "mes", "tes", "ses", "notre", "votre", "leur", "nos", "vos", "leurs"]
69
formesAdjectifsDémonstratifs = ["ce", "cet", "cette", "ces"]
70

    
71
formesPronomsPersonnels = ["je", "tu", "il", "elle", "on", "nous", "vous", "ils", "elles", "moi", "toi", "eux", "me", "te", "se", "lui", "leur"]
72
formesPronomsAdverbiaux = ["en", "y"]
73
formesPronomsPossessifs = ["mien", "mienne", "miens", "miennes", "tien", "tienne", "tiens", "tiennes", "sien", "sienne", "siens", "siennes", "nôtre", "nôtres", "vôtre", "vôtres", "leur", "leurs"]
74
formesPronomsDémonstratifs = ["ce", "c'", "celui", "celle", "ceux", "celles", "ci", "ça", "ceci", "cela", "tel", "telle", "tels", "telles"]
75

    
76
toutesLesFormes = []
77
toutesLesFormes += formesArticlesDéfinis
78
toutesLesFormes += formesArticlesIndéfinis
79
toutesLesFormes += formesDéterminantsPossessifs
80
toutesLesFormes += formesAdjectifsDémonstratifs
81
toutesLesFormes += formesPronomsPersonnels
82
toutesLesFormes += formesPronomsAdverbiaux
83
toutesLesFormes += formesPronomsPossessifs
84
toutesLesFormes += formesPronomsDémonstratifs
85

    
86
/** Fin de la déclaration des formes **/
87

    
88

    
89

    
90
def testRules(def positions, def Mention) {
91
        def catégorie = null
92
    def forme = CQI.cpos2Str(word.getQualifiedName(), positions)[0].toLowerCase()
93
    
94
        if (Mention.length == 1) {    
95
            
96
                     if (Mention.first() == "NAM"    ) catégorie = "GN.NAM"
97
                else if (Mention.first() == "DET:POS") catégorie = "DET.POS"
98
                else if (Mention.first() == "PRO:PER") {
99
                        if (formesPronomsAdverbiaux.contains(forme)) catégorie = "PRO.ADV"
100
                        else catégorie = "PRO.PER"
101
                }
102
                else if (Mention.first() == "PRO:DEM") catégorie = "PRO.DEM"
103
                else if (Mention.first() == "PRO:IND") catégorie = "PRO.IND"
104
                else if (Mention.first() == "PRO:REL") catégorie = "PRO.REL"
105
                else if (Mention.first().contains("VER:")) catégorie = "SUJ.ZERO"
106
                else if (Mention.first() == "PRO") catégorie = "PRO.INT"
107
                
108
                // GN indéfinis sans articles
109
                else if (Mention.first() == "NOM") catégorie = "GN.IND"
110
                else if (Mention.first() == "ADJ") catégorie = "GN.IND"
111
                
112
                // gestion des erreurs de TreeTagger
113
                else if (Mention.first() == "KON") catégorie = "PRO.REL" // Le 'que' dans une mention simple est un relatif
114
                else if (Mention.first() == "DET:ART") catégorie = "PRO.PER" // le, les
115
                else if (forme == "en") catégorie = "PRO.ADV"
116
                
117
                else if (Mention.first() == "ADV") catégorie = "ERREUR"  // un adverbe seul n'est jamais référentiel
118
                else if (Mention.first() == "PRE") catégorie = "ERREUR"  // une preposition seule n'est jamais référentielle
119
                else if (Mention.first() == "ADJ") catégorie = "ERREUR"  // un adjectif seul n'est jamais référentiel
120
                else if (Mention.first() == "INT") catégorie = "ERREUR"  // une interjection seule n'est jamais référentielle
121
                
122
                else catégorie = "PRO.CHECK"                
123
        } 
124
        
125
        else if (Mention.length == 2) {
126
                     if (Mention.contains("NAM")) catégorie = "GN.NAM"
127
                else if (Mention[1] == "PRO:POS") catégorie = "PRO.POS"  // "les miens"
128
                else if (Mention[1] == "NUM"    ) catégorie = "PRO.NUM"  // "les deux"
129
                else if (Mention[1] == "PRO:DEM") catégorie = "PRO.DEM"  // "Tout cela"
130
                else if (Mention[0] == "PRO:IND") catégorie = "GN.IND"   // "Quelques trucs"
131
                else if (Mention.contains("PRO:REL")) catégorie = "PRO.REL"
132
                else if ((Mention[0].contains("DET")) && (Mention[1] == "PROind")) catégorie = "PRO.IND" // des autres
133
                else if (Mention[1].contains("VER:")) catégorie = "SUJ.ZERO"
134
                else if (!Mention.contains("NOM") && !Mention.contains("ADJ")) {
135
                        if (Mention[0] == "PRO:DEM") catégorie = "PRO.DEM"
136
                        else catégorie = "PRO.CHECK"
137
                }
138
                else catégorie = "GN.CHECK"            
139
        } 
140
        
141
        if ( (catégorie == null) || (catégorie == "GN.CHECK") ) {
142
                // on est dans les GN
143
                     if (Mention[0] == "DET:POS" ) catégorie = "GN.POS"
144
                else if (Mention[0] == "NUM"     ) catégorie = "GN.NUM"
145
                else if (Mention[0] == "PRO:DEM" ) catégorie = "GN.DEM"
146
                else if (Mention[0] == "PRP:det" ) catégorie = "GN.DEF"
147
                else if (formesArticlesIndéfinis.contains(forme) || (forme == "une")) catégorie = "GN.IND" 
148
                else if (formesArticlesDéfinis.contains(forme))   catégorie = "GN.DEF"
149
                else if (Mention[0] == "PRO:IND" ) catégorie = "GN.IND"
150
                else if (Mention[0] == "PRP" ) catégorie = "GN.IND"
151
                else if (Mention[0] == "ADJ" ) catégorie = "GN.IND"
152
                else if (Mention[0] == "NOM" ) catégorie = "GN.IND"                
153
                else if (Mention.contains("NAM")) catégorie = "GN.NAM"
154
                else catégorie = "TEST"
155
        }
156
                
157
        return catégorie
158
}
159

    
160
//
161
// FIN DE LA DÉFINITION DES RÈGLES
162
//
163

    
164
// CORPS DU SCRIPT
165

    
166
if (!(corpusViewSelection instanceof MainCorpus)) {
167
        println "Corpora selection is not a Corpus"
168
        return
169
}
170

    
171
// BEGINNING OF PARAMETERS
172
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
173
def unit_type
174
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="pos")
175
def pos_property_name
176
@Field @Option(name="reset", usage="", widget="Boolean", required=true, def="true")
177
def reset
178
if (!ParametersDialog.open(this)) return
179

    
180
corpus = corpusViewSelection
181
CQI = CQPSearchEngine.getCqiClient()
182
word = corpus.getWordProperty()
183
posProperty = corpus.getProperty(pos_property_name)
184
if (posProperty == null) {
185
        println "Error: CQP corpus does not contains the word property with name=$pos_property_name"
186
        return
187
}
188
analecCorpus = URSCorpora.getCorpus(corpus)
189
vue = URSCorpora.getVue(corpus)
190
structure = analecCorpus.getStructure()
191
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
192
        println "Error: corpus structure does not contains unit with name=$unit_type"
193
        return
194
}
195

    
196
CATEGORIE = "CATEGORIE"
197
// Si la structure d'annotation ne contient pas CATEGORIE, on la crée avec ses valeurs
198
if (!structure.getUniteProperties(unit_type).contains(CATEGORIE)) { 
199

    
200
// FIXME: dans le script original (see also
201
// http://forge.cbp.ens-lyon.fr/redmine/issues/2065), on utilise
202
// analecCorpus.ajouterProp/Val, mais cela ne marche pas dans ma version de
203
// TXM-Analec --> je retourne donc à structure.ajouterProp/Val
204

    
205
// la propriété
206
        structure.ajouterProp(Unite.class, unit_type, CATEGORIE)
207
// les valeurs
208
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.NAM")
209
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.DEF")
210
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.IND")
211
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.POS")
212
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.DEM")
213
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.NUM")
214
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN.CHECK")
215
        
216
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "DET.POS")
217
        
218
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.PER")
219
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.ADV")
220
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.IND")
221
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.DEM")
222
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.POS")
223
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.NUM")
224
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.INT")
225
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.REL")
226
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.CHECK")
227
        
228
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "SUJ.ZERO")
229
        
230
        structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "ERREUR")
231
}
232

    
233
def nModified = 0
234
def nIgnored = 0
235

    
236
errors = new HashMap()
237
def units = analecCorpus.getUnites(unit_type)
238
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
239
for (Unite unit : units) { // process all units
240
        
241
        def prop = unit.getProp(CATEGORIE)
242
        if (!reset && prop != null && prop.length() > 0) continue // l'unité a déjà une CATEGORIE
243
        
244
        int[] positions = null
245
        if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
246
        else positions = (unit.getDeb()..unit.getFin())
247
        
248
        def Mention = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
249
        def cat = testRules(positions, Mention)
250

    
251
        if (cat != null) {
252
                // following line in the original script but doesn't work for me:
253
      // vue.setValeurChamp(unit, CATEGORIE, cat)
254
      unit.getProps().put(CATEGORIE, cat)
255
                nModified++
256
        } else {
257
                nIgnored++
258
        }
259
}
260

    
261
println "Result:"
262
println "- $nModified units of type $unit_type have been modified."
263
println "- $nIgnored units of type $unit_type have not been modified.\n"
264

    
265
if (errors.size() > 0) {
266
        println "Some rules should be added to this macro to process the following remaining 'FROPOS / words' values:"
267
        errors.keySet().each { println "fropos="+it+"\twords="+errors[it].join(" | ") }
268
}
269

    
270
// udpate the view (also see also
271
// http://forge.cbp.ens-lyon.fr/redmine/issues/2065)
272
URSCorpora.getVue(analecCorpus).retablirVueParDefaut()