Révision 2065

tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/LongueurDesMentionsMacro.groovy (revision 2065)
1
package org.txm.macro.urs.democrat
2

  
3
import org.apache.commons.lang.*
4
import org.kohsuke.args4j.*
5
import groovy.transform.*
6
import org.txm.*
7
import org.txm.rcp.swt.widget.parameters.*
8
import org.txm.annotation.urs.*
9
import org.txm.searchengine.cqp.*
10
import org.txm.searchengine.cqp.corpus.*
11
import visuAnalec.Message.*
12
import visuAnalec.donnees.*
13
import visuAnalec.elements.*
14
import visuAnalec.vue.*
15

  
16
/*
17
 Calcule la longueur des mentions et attribue une valeur (1, 2, 3 ou plus) dans la propriété "LONGUEUR"
18
 */
19

  
20
nLongueur1 = 0
21
nLongueur2 = 0
22
nLongueur3 = 0
23

  
24
def testRules(def positions, def Mention) {
25

  
26
	if (Mention.length == 1) {
27
		catégorie = "1"
28
		nLongueur1++
29
	}
30
	else if (Mention.length == 2) {
31
		catégorie = "2"
32
		nLongueur2++
33
	}
34
	else {
35
		catégorie = "3 ou plus"
36
		nLongueur3++
37
	}
38

  
39
	return catégorie
40
}
41

  
42
//
43
// FIN DE LA DÉFINITION DES RÈGLES
44
//
45

  
46
// CORPS DU SCRIPT
47

  
48
if (!(corpusViewSelection instanceof MainCorpus)) {
49
	println "Corpora selection is not a Corpus: "+corpusViewSelection
50
	return
51
}
52

  
53
// BEGINNING OF PARAMETERS
54
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
55
def unit_type
56
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="pos")
57
def pos_property_name
58
@Field @Option(name="reset", usage="", widget="Boolean", required=true, def="true")
59
def reset
60
if (!ParametersDialog.open(this)) return
61

  
62
corpus = corpusViewSelection
63
CQI = CQPSearchEngine.getCqiClient()
64
word = corpus.getWordProperty()
65
posProperty = corpus.getProperty(pos_property_name)
66
if (posProperty == null) {
67
	println "Error: CQP corpus does not contains the word property with name=$pos_property_name"
68
	return
69
}
70
analecCorpus = URSCorpora.getCorpus(corpus)
71
vue = URSCorpora.getVue(corpus)
72
structure = analecCorpus.getStructure()
73
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
74
	println "Error: corpus structure does not contains unit with name=$unit_type"
75
	return
76
}
77

  
78
LONGUEUR = "LONGUEUR"
79
// Si la structure d'annotation ne contient pas LONGUEUR, on la crée avec ses valeurs
80
if (!structure.getUniteProperties(unit_type).contains(LONGUEUR)) {
81
	// la propriété
82
	analecCorpus.ajouterProp(Unite.class, unit_type, LONGUEUR)
83
	// les valeurs
84

  
85
	structure.ajouterVal(Unite.class, unit_type, LONGUEUR, "1")
86
	structure.ajouterVal(Unite.class, unit_type, LONGUEUR, "2")
87
	structure.ajouterVal(Unite.class, unit_type, LONGUEUR, "3 ou plus")
88

  
89
	//...
90
}
91

  
92
def nModified = 0
93
def nIgnored = 0
94

  
95
errors = new HashMap()
96
def units = analecCorpus.getUnites(unit_type)
97
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
98
for (Unite unit : units) { // process all units
99

  
100
	def prop = unit.getProp(LONGUEUR)
101
	if (!reset && prop != null && prop.length() > 0) continue // l'unité a déjà une LONGUEUR
102

  
103
		int[] positions = null
104
	if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
105
	else positions = (unit.getDeb()..unit.getFin())
106

  
107
	def Mention = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
108
	def cat = testRules(positions, Mention)
109

  
110
	if (cat != null) {
111
		vue.setValeurChamp(unit, LONGUEUR, cat)
112
		nModified++
113
	} else {
114
		nIgnored++
115
	}
116
}
117

  
118
println "Result:"
119
println "- $nModified units of type $unit_type have been modified."
120
println "- $nIgnored units of type $unit_type have not been modified.\n"
121

  
122
println "- $nLongueur1 mentions de longueur 1."
123
println "- $nLongueur2 mentions de longueur 2."
124
println "- $nLongueur3 mentions de longueur 3 ou plus.\n"
125

  
126
if (errors.size() > 0) {
127
	println "Some rules should be added to this macro to process the following remaining 'FROPOS / words' values:"
128
	errors.keySet().each { println "fropos="+it+"\twords="+errors[it].join(" | ") }
129
}
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/Fropos2CategorieMacro.groovy (revision 2065)
1
package org.txm.macro.urs.democrat
2

  
3
import org.apache.commons.lang.*
4
import org.kohsuke.args4j.*
5
import groovy.transform.*
6
import org.txm.*
7
import org.txm.rcp.swt.widget.parameters.*
8
import org.txm.annotation.urs.*
9
import org.txm.searchengine.cqp.*
10
import org.txm.searchengine.cqp.corpus.*
11
import visuAnalec.Message.*
12
import visuAnalec.donnees.*
13
import visuAnalec.elements.*
14
import visuAnalec.vue.*
15

  
16
def testRules(def positions, def Mention) {
17
	def catégorie = null
18

  
19
// DÉFINITION DES RÈGLES
20
// elles sont testées les unes après les autres. 
21
// Dès qu'une règle est appliquée les suivantes sont ignorées.
22

  
23
// Règles de type CONTIENT
24

  
25
	     if (Mention.contains("NOMpro")) catégorie = "Nom Propre"
26
	else if (Mention.contains("DETpos")) catégorie = "Dét Possessif"
27
//  ...
28

  
29
// Règles de type COMMENCE ET NE CONTIENT PAS	
30

  
31
	else if (Mention.first() == "DETpos" && !Mention.contains("NOMpro")) catégorie = "GN Possessif"
32
	else if (Mention.first() == "DETdem" && !Mention.contains("NOMpro")) catégorie = "GN Démonstratif"
33
//  ...
34

  
35
// Règles de type CONTIENT PLUSIEURS	
36

  
37
	else if (Mention.contains("PROadv") || Mention.contains("ADVgen.PROadv")) catégorie = "Pronom Adverbial"
38
//  ...
39

  
40
// Règles de type CONTIENT ET NE CONTIENT PAS
41

  
42
	else if (
43
			 ( Mention.contains("DETdef") || Mention.contains("PRE.DETdef") )
44
			  &&
45
			  !Mention.contains("PROpos") && !Mention.contains("NOMpro") && !Mention.contains("PROcar")
46
			) catégorie = "GN Défini"
47
//  ...	
48

  
49
// Fin des règles, aucune n'a matchée. On stocke le pattern  qu'on affichera à la fin.
50
	else {
51
		def forms = CQI.cpos2Str(word.getQualifiedName(), positions)
52
		if (!errors.containsKey(Mention)) errors[Mention] = new HashSet()
53
		errors[Mention] << forms
54
	}
55
	
56
	return catégorie
57
}
58

  
59
//
60
// FIN DE LA DÉFINITION DES RÈGLES
61
//
62

  
63
// CORPS DU SCRIPT
64

  
65
if (!(corpusViewSelection instanceof MainCorpus)) {
66
	println "Corpora selection is not a Corpus"
67
	return
68
}
69

  
70
// BEGINNING OF PARAMETERS
71
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
72
def unit_type
73
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="pos")
74
def pos_property_name
75
@Field @Option(name="reset", usage="", widget="Boolean", required=true, def="true")
76
def reset
77
if (!ParametersDialog.open(this)) return
78

  
79
corpus = corpusViewSelection
80
CQI = CQPSearchEngine.getCqiClient()
81
word = corpus.getWordProperty()
82
posProperty = corpus.getProperty(pos_property_name)
83
if (posProperty == null) {
84
	println "Error: CQP corpus does not contains the word property with name=$pos_property_name"
85
	return
86
}
87
analecCorpus = URSCorpora.getCorpus(corpus)
88
vue = URSCorpora.getVue(corpus)
89
structure = analecCorpus.getStructure()
90
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
91
	println "Error: corpus structure does not contains unit with name=$unit_type"
92
	return
93
}
94

  
95
CATEGORIE = "CATEGORIE"
96
// Si la structure d'annotation ne contient pas CATEGORIE, on la crée avec ses valeurs
97
if (!structure.getUniteProperties(unit_type).contains(CATEGORIE)) { 
98
// la propriété
99
	analecCorpus.ajouterProp(Unite.class, unit_type, CATEGORIE)
100
// les valeurs
101
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Nom Propre")
102
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Impersonnel")
103
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Interrogatif")
104
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Pronom cardinal")
105
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Démonstratif")
106
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Indéfini")
107
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom ordinal")
108
	analecCorpus.ajouterVal(Unite.class, unit_type, CATEGORIE, "Pronom Relatif")
109
//...
110
}
111

  
112
def nModified = 0
113
def nIgnored = 0
114

  
115
errors = new HashMap()
116
def units = analecCorpus.getUnites(unit_type)
117
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
118
for (Unite unit : units) { // process all units
119
	
120
	def prop = unit.getProp(CATEGORIE)
121
	if (!reset && prop != null && prop.length() > 0) continue // l'unité a déjà une CATEGORIE
122
	
123
	int[] positions = null
124
	if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
125
	else positions = (unit.getDeb()..unit.getFin())
126
	
127
	def Mention = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
128
	def cat = testRules(positions, Mention)
129
	
130
	if (cat != null) {
131
		vue.setValeurChamp(unit, CATEGORIE, cat)
132
		nModified++
133
	} else {
134
		nIgnored++
135
	}
136
}
137

  
138
println "Result:"
139
println "- $nModified units of type $unit_type have been modified."
140
println "- $nIgnored units of type $unit_type have not been modified.\n"
141

  
142
if (errors.size() > 0) {
143
	println "Some rules should be added to this macro to process the following remaining 'FROPOS / words' values:"
144
	errors.keySet().each { println "fropos="+it+"\twords="+errors[it].join(" | ") }
145
}
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/Frpos2CategorieDemocratMacro.groovy (revision 2065)
1
// @author Bruno Oberlé (2017-04-01 21:50)
2

  
3
/*
4
Définit la catégorie grammaticale du maillon d'après le champ `frpos'
5
(tagset de TreeTagger).  Le script est adapté de
6
http://svn.code.sf.net/p/txm/code/trunk/plugins/Analec/AnalecRCP/src/org/txm/macro/analec/Fropos2CategorieMacro.groovy.
7

  
8
Voici la liste des catégories grammaticales retenues (manuel d'annotation de
9
Democrat):
10
- GN: Groupe Nominal (le petit chat, le chat, le même, ce chat etc.)
11
- POSS: Possessif (mon, ton son, ma, ta, sa, mes, tes, ses, notre, votre,
12
  leur, nos, vos, leurs)
13
- PR: Pronom (moi, toi, lui, elle, nous, vous, eux, elles, le tien, le mien,
14
  moi-même etc.)
15
- PR_CL_O: Pronom Clitique Objet (me, te, le, la, les, lui, leur, y, en)
16
- PR_CL_R: Pronom Clitique Réfléchi
17
- PR_CL_S: Pronom Clitique Sujet (je, tu, il, elle, on, nous, vous, ils,
18
  elles)
19
- PR_REL: Pronom Relatif (qui, que, quoi, dont, où, lequel, quiconque etc.)
20
- PR_WH: Pronom Interrogatif (qui, que, quoi, lequel etc.)
21

  
22
Le script ne peut pas désambiguïser les pronoms clitiques de même forme
23
(`nous' est-il un sujet, un objet ou un réfléchi?).  Dans ce cas, le script
24
opte pour le sujet (ou pour l'objet si l'ambiguïté n'est que entre objet et
25
réfléchi).
26

  
27
Quand il n'y a aucune information disponible (erreurs de l'étiqueteur), la
28
valeur est UNDEFINED.
29

  
30
L'algorithme est décrit ici:
31
https://groupes.renater.fr/wiki/democrat/prive/txm_annotation_exploitation
32

  
33
*/
34

  
35
package org.txm.macro.urs.democrat
36

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

  
50
def testClitic(def position, def frpos) {
51

  
52
   // je me sers de la forme, parce qu'il est difficile de savoir quel est le
53
   // lemme de "elle" ("il"?), de "te" ("tu"?) ou encore de "leur"
54
   def form = CQI.cpos2Str(word.getQualifiedName(), position)[0].toLowerCase()
55
   if (     form == "je" || form == "j'"
56
         || form == "tu" || form == "t'"
57
         || form == "il"
58
         || form == "elle"
59
         || form == "on"
60
         || form == "vous"
61
         || form == "nous"
62
         || form == "ils"
63
         || form == "elles" ) {
64
      return "PR_CL_S"
65
   } else if (form == "me" || form == "m'"
66
           || form == "te"
67
           || form == "le" || form == "l'"
68
           || form == "la"
69
           || form == "lui"
70
           || form == "leur"
71
           || form == "les" ) {
72
      return "PR_CL_O"
73
   } else if (form == "se" || form == "s'") {
74
      return "PR_CL_R"
75
   }
76
   return null
77

  
78
}
79

  
80
def testPhrase(def positions, def Mention) {
81

  
82
   // on doit regarder ce qui apparaît en premier:
83
   // - ce peut être un nom, comme dans `le petit chat que j'ai adopté'
84
   // - ce peut être un pronom relatif, comme dans `(le livre) dans lequel
85
   // j'ai lu cette histoire...'
86
   // NOTE: dans Democrat, on n'annote pas, bizarrement, la relative dans le
87
   // maillon, donc, dans un GN on n'a jamais de relatif inclus.  On aura donc
88
   // toujours `[le petit chat] [que] [j']ai adopté'.  Mais tout le monde
89
   // n'annote pas de la sorte...
90
   for (def i=0; i<Mention.length; i++) {
91
         def mention = Mention[i]
92
         //def form = CQI.cpos2Str(word.getQualifiedName(), positions[i])[0]
93
         if (mention == "NOM" || mention == "NAM") {
94
            return "GN"
95
         } else if (mention == "PRO:REL") {
96
            return "PR_REL"
97
         }
98
    }
99

  
100
    return null
101

  
102
}
103

  
104
def testWhPronoun(position, mention) {
105
   def form = CQI.cpos2Str(word.getQualifiedName(), position)[0]
106
   if (mention == "PRO" && (form == "qui" || form == "que" || form == "lequel")) {
107
      return "PR_WH"
108
   }
109
   return null
110

  
111
}
112

  
113
def testRules(def positions, def Mention) {
114
	def catégorie = null
115

  
116
   // a possessive (mon, ma...)
117
   if (Mention.length == 1 && Mention.contains("DET:POS"))
118
      catégorie = "POSS"
119

  
120
   // a clitic (subject: je, tu...; object: me, te; reflexive: se)
121
   if (!catégorie && Mention.length == 1 && Mention.contains("PRO:PER"))
122
      catégorie = testClitic(positions[0], Mention[0])
123

  
124
   // an interrogative pronoun
125
   if (!catégorie && Mention.length == 1)
126
      catégorie = testWhPronoun(positions[0], Mention[0])
127

  
128
   // a noun phrase or a relative pronoun
129
   if (!catégorie)
130
      catégorie = testPhrase(positions, Mention)
131

  
132
   // some other kind of pronouns
133
   if (!catégorie
134
         && (   Mention.contains("PRO")
135
             || Mention.contains("PRO:POSS")
136
             || Mention.contains("PRO:IND")
137
             || Mention.contains("PRO:DEM")
138
             || Mention.contains("PRO:PER") )
139
         && !Mention.contains("NOM")
140
         && !Mention.contains("NAM") )
141
      catégorie = "PRO"
142

  
143
// Fin des règles, aucune n'a matchée. On stocke le pattern  qu'on affichera à la fin.
144
   if (!catégorie) {
145
      catégorie = "UNDEFINED" // clear the field
146
		def forms = CQI.cpos2Str(word.getQualifiedName(), positions)
147
		if (!errors.containsKey(Mention)) errors[Mention] = new HashSet()
148
		errors[Mention] << forms
149
	}
150
	
151
	return catégorie
152
}
153

  
154
//
155
// FIN DE LA DÉFINITION DES RÈGLES
156
//
157

  
158
// CORPS DU SCRIPT
159

  
160
if (!(corpusViewSelection instanceof MainCorpus)) {
161
	println "Corpora selection is not a Corpus"
162
	return
163
}
164

  
165
// BEGINNING OF PARAMETERS
166
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
167
def unit_type
168
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="pos")
169
def pos_property_name
170
@Field @Option(name="reset", usage="", widget="Boolean", required=true, def="true")
171
def reset
172
if (!ParametersDialog.open(this)) return
173

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

  
190
CATEGORIE = "CATEGORIE"
191
// Si la structure d'annotation ne contient pas CATEGORIE, on la crée avec ses valeurs
192
if (!structure.getUniteProperties(unit_type).contains(CATEGORIE)) { 
193

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

  
199
// la propriété
200
	structure.ajouterProp(Unite.class, unit_type, CATEGORIE)
201
// les valeurs
202
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN")
203
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "POSS")
204
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO")
205
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_O")
206
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_S")
207
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_R")
208
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_REL")
209
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_WH")
210
//...
211
}
212

  
213
def nModified = 0
214
def nIgnored = 0
215

  
216
errors = new HashMap()
217
def units = analecCorpus.getUnites(unit_type)
218
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
219
for (Unite unit : units) { // process all units
220
	
221
	def prop = unit.getProp(CATEGORIE)
222
	if (!reset && prop != null && prop.length() > 0) continue // l'unité a déjà une CATEGORIE
223
	
224
	int[] positions = null
225
	if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
226
	else positions = (unit.getDeb()..unit.getFin())
227
	
228
	def Mention = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
229
	def cat = testRules(positions, Mention)
230

  
231
	if (cat != null) {
232
		// following line in the original script but doesn't work for me:
233
      // vue.setValeurChamp(unit, CATEGORIE, cat)
234
      unit.getProps().put(CATEGORIE, cat)
235
		nModified++
236
	} else {
237
		nIgnored++
238
	}
239
}
240

  
241
println "Result:"
242
println "- $nModified units of type $unit_type have been modified."
243
println "- $nIgnored units of type $unit_type have not been modified.\n"
244

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

  
250
// udpate the view (also see also
251
// http://forge.cbp.ens-lyon.fr/redmine/issues/2065)
252
URSCorpora.getVue(analecCorpus).retablirVueParDefaut()
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/PremierMaillonMacro.groovy (revision 2065)
1
// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
2
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
3
// @author mdecorde
4
// @author sheiden
5
// STANDARD DECLARATIONS
6
package org.txm.macro.urs.democrat
7

  
8
import org.kohsuke.args4j.*
9

  
10
import groovy.transform.Field
11

  
12
import org.txm.rcp.swt.widget.parameters.*
13
import org.txm.annotation.urs.*
14
import org.txm.searchengine.cqp.corpus.*
15

  
16
import visuAnalec.donnees.Structure;
17
import visuAnalec.elements.Unite;
18
import visuAnalec.vue.Vue
19

  
20
if (!(corpusViewSelection instanceof MainCorpus)) {
21
	println "Corpora selection is not a Corpus"
22
	return;
23
}
24

  
25
// BEGINNING OF PARAMETERS
26
@Field @Option(name="unit_type",usage="", widget="String", required=true, def="MENTION")
27
String unit_type
28
@Field @Option(name="reset",usage="", widget="Boolean", required=true, def="true")
29
boolean reset
30

  
31
if (!ParametersDialog.open(this)) return;
32

  
33
MainCorpus corpus = corpusViewSelection
34
def analecCorpus = URSCorpora.getCorpus(corpus);
35
Structure structure = analecCorpus.getStructure()
36
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
37
	println "Error: corpus structure does not contains unit with name=$unit_type"
38
	return
39
}
40
def props = structure.getUniteProperties(unit_type)
41

  
42
String NEW = "NEW"
43
String REF = "REF"
44
String YES = "YES"
45
String NO = "NO"
46
if (!props.contains(NEW)) { // update the structure if needed
47
	analecCorpus.ajouterProp(Unite.class, unit_type, NEW);
48
	analecCorpus.ajouterVal(Unite.class, unit_type, NEW, "YES");
49
	analecCorpus.ajouterVal(Unite.class, unit_type, NEW, "NO");
50
}
51

  
52
if (!props.contains(REF)) { // check the unit_type units have the REF property
53
	println "Error: $unit_type units have no proprerty named 'REF'"
54
	return
55
}
56

  
57
int nIgnored = 0; // number of units ignored
58
int nYes = 0 // number of "YES" unit set
59
int nNo = 0 // number of "NO" unit set
60

  
61
def allRefs = new HashSet<String>() // store the references already seen, allow to set the 'NEW' property to 'YES' or 'NO'
62
def units = analecCorpus.getUnites(unit_type)
63
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
64
for (Unite unit : units) {
65
	def prop = unit.getProp(NEW);
66
	def ref = unit.getProp(REF);
67
	if (reset || prop == null || prop.length() == 0) {
68
		if (allRefs.contains(ref)) {
69
			unit.getProps().put(NEW, NO)
70
			nNo++
71
		} else { // this is the first MENTION of the CHAINE
72
			allRefs << ref
73
			unit.getProps().put(NEW, YES)
74
			nYes++
75
		}
76
	} else {
77
		// nothing to do "NEW" already exists
78
		nIgnored++
79
	}
80
}
81

  
82
println "nIgnored=$nIgnored"
83
println "nYes=$nYes"
84
println "nNo=$nNo"
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/AjoutDefinitudeMacro.groovy (revision 2065)
1
// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
2
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
3
// @author mdecorde
4
// @author sheiden
5
// STANDARD DECLARATIONS
6
package org.txm.macro.urs.democrat
7

  
8
import org.apache.commons.lang.StringUtils;
9
import org.kohsuke.args4j.*
10

  
11
import groovy.transform.Field
12

  
13
import org.txm.Toolbox;
14
import org.txm.rcp.swt.widget.parameters.*
15
import org.txm.annotation.urs.*
16
import org.txm.searchengine.cqp.AbstractCqiClient;
17
import org.txm.searchengine.cqp.corpus.*
18
import org.txm.searchengine.cqp.CQPSearchEngine
19
import visuAnalec.Message.StructureEvent;
20
import visuAnalec.Message.TypeModifStructure;
21
import visuAnalec.donnees.Structure;
22
import visuAnalec.elements.Unite;
23
import visuAnalec.vue.Vue
24

  
25
if (!(corpusViewSelection instanceof MainCorpus)) {
26
	println "Corpora selection is not a Corpus"
27
	return;
28
}
29

  
30
// BEGINNING OF PARAMETERS
31
@Field @Option(name="unit_type",usage="", widget="String", required=true, def="MENTION")
32
String unit_type
33
@Field @Option(name="reset",usage="", widget="Boolean", required=true, def="false")
34
boolean reset
35

  
36
if (!ParametersDialog.open(this)) return;
37

  
38
MainCorpus corpus = corpusViewSelection
39
AbstractCqiClient CQI = CQPSearchEngine.getCqiClient();
40
def word = corpus.getWordProperty()
41
def analecCorpus = URSCorpora.getCorpus(corpus);
42
Structure structure = analecCorpus.getStructure()
43
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
44
	println "Error: corpus structure does not contains unit with name=$unit_type"
45
	return
46
}
47
def props = structure.getUniteProperties(unit_type)
48

  
49
String DEFINITUDE = "DEFINITUDE"
50
if (!props.contains(DEFINITUDE)) { // update the structure if needed
51
	analecCorpus.ajouterProp(Unite.class, unit_type, DEFINITUDE);
52
	analecCorpus.ajouterVal(Unite.class, unit_type, DEFINITUDE, "DEFINI");
53
	analecCorpus.ajouterVal(Unite.class, unit_type, DEFINITUDE, "INDEFINI");
54
	analecCorpus.ajouterVal(Unite.class, unit_type, DEFINITUDE, "DEMONSTRATIF");
55
	analecCorpus.ajouterVal(Unite.class, unit_type, DEFINITUDE, "AMBIGU");
56
	analecCorpus.ajouterVal(Unite.class, unit_type, DEFINITUDE, "NONE");
57
}
58

  
59
int nIgnored = 0 // number of ignored units
60
int nModified = 0 // number of modified units
61
int nDefini = 0 // number of "DEFINI" units
62
int nIndefini = 0 // number of "InDEFINI" units
63
int nDemonstratif = 0 // number of "DEMONSTRATIF" units
64
int nAmbigu = 0 // number of "AMBIGU" units
65
int nNone = 0 // number of "NONE" units
66

  
67
def units = analecCorpus.getUnites(unit_type)
68
units = units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
69
for (Unite unit : units) { // process all units
70
	
71
	def prop = unit.getProp(DEFINITUDE);
72
	
73
	int[] pos = null
74
	if (unit.getDeb() == unit.getFin()) pos = [unit.getDeb()]
75
	else pos = (unit.getDeb()..unit.getFin())
76
	def form = StringUtils.join(CQI.cpos2Str(word.getQualifiedName(), pos), " ")
77
	
78
	if (reset || prop == null || prop.length() == 0 || prop.equals("NONE")) {
79
		// petits ajouts à faire ? : |(ses\s.+)|(Ses\s.+)|(son\s.+)|(Son\s.+)|(sa\s.+)|(Sa\s.+)|(leurs?\s.+)|(Leurs?\s.+)|(tous\s.+)|(Tous\s.+)|(toutes\s.+)|(Toutes\s.+)
80
		if (form =~ /^(le\s.+)|(Les\s.+)|(Le\s.+)|(la\s.+)|(La\s.+)|(l'.+)|(L'.+)|(les\s.+)|(au\s.+)|(Au\s.+)|(aux\s.+)|(Aux\s.+)|(du\s.+)|(Du\s.+)/) {
81
			unit.getProps().put(DEFINITUDE, "DEFINI")
82
			nDefini++
83
		} else if (form =~ /^(un\s.+)|(une\s.+)|(Un\s.+)|(Une\s.+)|(Chaque\s.+)|(chaque\s.+)|(Certains\s.+)|(Certaines\s.+)|(certains\s.+)|(certaines\s.+)|(aucun\s.+)|(aucune\s.+)|(Aucun\s.+)|(Aucunes\s.+)|(Autre\s.+)|(Autre\s.+)|(autres\s.+)|(autre\s.+)|(quelque\s.+)|(quelques\s.+)|(Quelque\s.+)|(Quelques\s.+)/) {
84
			unit.getProps().put(DEFINITUDE, "INDEFINI")
85
			nIndefini++
86
		} else if (form =~ /^(ce\s.+)|(cette\s.+)|(Cette\s.+)|(cet\s.+)|(ces\s.+)|(Ce\s.+)|(Cet\s.+)|(Ces\s.+)/) {
87
			unit.getProps().put(DEFINITUDE, "DEMONSTRATIF")
88
			nDemonstratif++
89
		} else if (form =~ /^(des\s.+)|(de\s.+)|(Des\s.+)|(De\s.+)/) {
90
			unit.getProps().put(DEFINITUDE, "AMBIGU")
91
			nAmbigu++
92
		} else {
93
			unit.getProps().put(DEFINITUDE, "NONE")
94
			nNone++;
95
		}
96
		nModified++
97
		
98
	} else {
99
		// nothing to do
100
		nIgnored++
101
	}
102
}
103

  
104
println "nIgnored=$nIgnored"
105
println "nModified=$nModified"
106
println " nDefini=$nDefini"
107
println " nIndefini=$nIndefini"
108
println " nDemonstratif=$nDemonstratif"
109
println " nAmbigu=$nAmbigu"
110
println " nNone=$nNone"
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/Frpos2CattexMacro.groovy (revision 2065)
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.democrat
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()
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/PROPERanaphoriquesMacro.groovy (revision 2065)
1
package org.txm.macro.urs.democrat
2

  
3
import org.apache.commons.lang.*
4
import org.kohsuke.args4j.*
5
import groovy.transform.*
6
import org.txm.*
7
import org.txm.rcp.swt.widget.parameters.*
8
import org.txm.annotation.urs.*
9
import org.txm.searchengine.cqp.*
10
import org.txm.searchengine.cqp.corpus.*
11
import visuAnalec.Message.*
12
import visuAnalec.donnees.*
13
import visuAnalec.elements.*
14
import visuAnalec.vue.*
15

  
16
/*
17
   Distingue les Pronoms Personnels Anaphoriques (PRO.PERA) des Pronoms Personnels Déictiques (PRO.PERD)
18
   PRO.PERD = frlemma(je|me|moi|tu|te|toi|nous|vous)
19
   On rajoute aussi quelques graphies anciennes que TreeTagger ne connaît pas forcément.
20
   Inutile de différencier minuscules et majuscules. Le test gère cela très bien.
21
   Auteur : Matthieu Quignard (ICAR)
22
   Date : 19/12/2017
23
 */
24

  
25
listeLemmesDeictiques = ["je", "me", "moi", "tu", "te", "toi", "nous", "vous"]
26
listeFormesDeictiques = ["moy", "toy"]
27

  
28

  
29
// CORPS DU SCRIPT
30

  
31
if (!(corpusViewSelection instanceof MainCorpus)) {
32
	println "Corpora selection is not a Corpus: "+corpusViewSelection
33
	return
34
}
35

  
36
// BEGINNING OF PARAMETERS
37
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
38
def unit_type
39
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="frlemma")
40
def pos_property_name
41
if (!ParametersDialog.open(this)) return
42

  
43
corpus = corpusViewSelection
44
CQI = CQPSearchEngine.getCqiClient()
45
word = corpus.getWordProperty()
46
posProperty = corpus.getProperty(pos_property_name)
47
if (posProperty == null) {
48
	println "Error: CQP corpus does not contains the word property with name=$pos_property_name"
49
	return
50
}
51
analecCorpus = URSCorpora.getCorpus(corpus)
52
vue = URSCorpora.getVue(corpus)
53
structure = analecCorpus.getStructure()
54
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
55
	println "Error: corpus structure does not contains unit with name=$unit_type"
56
	return
57
}
58

  
59
CATEGORIE = "CATEGORIE"
60
structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.PERA")
61
structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO.PERD")
62

  
63
def nModified = 0
64
def nIgnored = 0
65
def nProPerA = 0
66
def nProPerD = 0
67

  
68
errors = new HashMap()
69
def units = analecCorpus.getUnites(unit_type)
70
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
71

  
72
for (Unite unit : units) { // process all units
73
	def prop = unit.getProp(CATEGORIE)
74
	
75
	if ( (prop == null) || (!prop.contains("PRO.PER")) ) {
76
		// On ne s'intéresse qu'aux pronoms personnels (PRO.PER)
77
		// Les autres sont ignorés
78
		nIgnored++
79
	} else {
80
		// Pour les mentions de type "PRO.PER", on cherche le premier mot
81
		int[] positions = null
82
		if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
83
		else positions = (unit.getDeb()..unit.getFin())
84
	
85
		// On récupère le lemme du premier mot
86
		def tags = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
87
		def firstTag = tags[0];
88
		
89
		// On récupère la forme du premier mot en minuscule
90
		def forme = CQI.cpos2Str(word.getQualifiedName(), positions)[0].toLowerCase()
91
		
92
		if (listeLemmesDeictiques.contains(firstTag)) {
93
			// Si le lemme est dans la liste de déictiques, on recatégorise en PRO.PERD
94
			vue.setValeurChamp(unit, CATEGORIE, "PRO.PERD")
95
			nProPerD++
96
		} else if (listeFormesDeictiques.contains(forme)) {
97
			// Si la forme du premier mot dans la liste des formes des déictiques, on recatégorise en PRO.PERD
98
			vue.setValeurChamp(unit, CATEGORIE, "PRO.PERD")
99
			nProPerD++
100
		} else {
101
			// Sinon on recatégorise en PRO.PERA
102
			vue.setValeurChamp(unit, CATEGORIE, "PRO.PERA")
103
			nProPerA++
104
		}
105
		nModified++
106
	}
107
}
108

  
109
println "Result:"
110
println "- $nModified units of type $unit_type have been modified."
111
println "- $nIgnored units of type $unit_type have not been modified.\n"
112

  
113
println "- $nProPerA mentions de ProPer anaphoriques."
114
println "- $nProPerD mentions de ProPer déictiques."
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/Frpos2CategorieMacro.groovy (revision 2065)
1
// @author Bruno Oberlé (2017-04-01 21:50)
2

  
3
/*
4
Définit la catégorie grammaticale du maillon d'après le champ `frpos'
5
(tagset de TreeTagger).  Le script est adapté de
6
http://svn.code.sf.net/p/txm/code/trunk/plugins/Analec/AnalecRCP/src/org/txm/macro/analec/Fropos2CategorieMacro.groovy.
7

  
8
Voici la liste des catégories grammaticales retenues (manuel d'annotation de
9
Democrat):
10
- GN: Groupe Nominal (le petit chat, le chat, le même, ce chat etc.)
11
- POSS: Possessif (mon, ton son, ma, ta, sa, mes, tes, ses, notre, votre,
12
  leur, nos, vos, leurs)
13
- PR: Pronom (moi, toi, lui, elle, nous, vous, eux, elles, le tien, le mien,
14
  moi-même etc.)
15
- PR_CL_O: Pronom Clitique Objet (me, te, le, la, les, lui, leur, y, en)
16
- PR_CL_R: Pronom Clitique Réfléchi
17
- PR_CL_S: Pronom Clitique Sujet (je, tu, il, elle, on, nous, vous, ils,
18
  elles)
19
- PR_REL: Pronom Relatif (qui, que, quoi, dont, où, lequel, quiconque etc.)
20
- PR_WH: Pronom Interrogatif (qui, que, quoi, lequel etc.)
21

  
22
Le script ne peut pas désambiguïser les pronoms clitiques de même forme
23
(`nous' est-il un sujet, un objet ou un réfléchi?).  Dans ce cas, le script
24
opte pour le sujet (ou pour l'objet si l'ambiguïté n'est que entre objet et
25
réfléchi).
26

  
27
Quand il n'y a aucune information disponible (erreurs de l'étiqueteur), la
28
valeur est UNDEFINED.
29

  
30
L'algorithme est décrit ici:
31
https://groupes.renater.fr/wiki/democrat/prive/txm_annotation_exploitation
32

  
33
*/
34

  
35
package org.txm.macro.urs.democrat
36

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

  
50
def testClitic(def position, def frpos) {
51

  
52
   // je me sers de la forme, parce qu'il est difficile de savoir quel est le
53
   // lemme de "elle" ("il"?), de "te" ("tu"?) ou encore de "leur"
54
   def form = CQI.cpos2Str(word.getQualifiedName(), position)[0].toLowerCase()
55
   if (     form == "je" || form == "j'"
56
         || form == "tu" || form == "t'"
57
         || form == "il"
58
         || form == "elle"
59
         || form == "on"
60
         || form == "vous"
61
         || form == "nous"
62
         || form == "ils"
63
         || form == "elles" ) {
64
      return "PR_CL_S"
65
   } else if (form == "me" || form == "m'"
66
           || form == "te"
67
           || form == "le" || form == "l'"
68
           || form == "la"
69
           || form == "lui"
70
           || form == "leur"
71
           || form == "les" ) {
72
      return "PR_CL_O"
73
   } else if (form == "se" || form == "s'") {
74
      return "PR_CL_R"
75
   }
76
   return null
77

  
78
}
79

  
80
def testPhrase(def positions, def Mention) {
81

  
82
   // on doit regarder ce qui apparaît en premier:
83
   // - ce peut être un nom, comme dans `le petit chat que j'ai adopté'
84
   // - ce peut être un pronom relatif, comme dans `(le livre) dans lequel
85
   // j'ai lu cette histoire...'
86
   // NOTE: dans Democrat, on n'annote pas, bizarrement, la relative dans le
87
   // maillon, donc, dans un GN on n'a jamais de relatif inclus.  On aura donc
88
   // toujours `[le petit chat] [que] [j']ai adopté'.  Mais tout le monde
89
   // n'annote pas de la sorte...
90
   for (def i=0; i<Mention.length; i++) {
91
         def mention = Mention[i]
92
         //def form = CQI.cpos2Str(word.getQualifiedName(), positions[i])[0]
93
         if (mention == "NOM" || mention == "NAM") {
94
            return "GN"
95
         } else if (mention == "PRO:REL") {
96
            return "PR_REL"
97
         }
98
    }
99

  
100
    return null
101

  
102
}
103

  
104
def testWhPronoun(position, mention) {
105
   def form = CQI.cpos2Str(word.getQualifiedName(), position)[0]
106
   if (mention == "PRO" && (form == "qui" || form == "que" || form == "lequel")) {
107
      return "PR_WH"
108
   }
109
   return null
110

  
111
}
112

  
113
def testRules(def positions, def Mention) {
114
	def catégorie = null
115

  
116
   // a possessive (mon, ma...)
117
   if (Mention.length == 1 && Mention.contains("DET:POS"))
118
      catégorie = "POSS"
119

  
120
   // a clitic (subject: je, tu...; object: me, te; reflexive: se)
121
   if (!catégorie && Mention.length == 1 && Mention.contains("PRO:PER"))
122
      catégorie = testClitic(positions[0], Mention[0])
123

  
124
   // an interrogative pronoun
125
   if (!catégorie && Mention.length == 1)
126
      catégorie = testWhPronoun(positions[0], Mention[0])
127

  
128
   // a noun phrase or a relative pronoun
129
   if (!catégorie)
130
      catégorie = testPhrase(positions, Mention)
131

  
132
   // some other kind of pronouns
133
   if (!catégorie
134
         && (   Mention.contains("PRO")
135
             || Mention.contains("PRO:POSS")
136
             || Mention.contains("PRO:IND")
137
             || Mention.contains("PRO:DEM")
138
             || Mention.contains("PRO:PER") )
139
         && !Mention.contains("NOM")
140
         && !Mention.contains("NAM") )
141
      catégorie = "PRO"
142

  
143
// Fin des règles, aucune n'a matchée. On stocke le pattern  qu'on affichera à la fin.
144
   if (!catégorie) {
145
      catégorie = "UNDEFINED" // clear the field
146
		def forms = CQI.cpos2Str(word.getQualifiedName(), positions)
147
		if (!errors.containsKey(Mention)) errors[Mention] = new HashSet()
148
		errors[Mention] << forms
149
	}
150
	
151
	return catégorie
152
}
153

  
154
//
155
// FIN DE LA DÉFINITION DES RÈGLES
156
//
157

  
158
// CORPS DU SCRIPT
159

  
160
if (!(corpusViewSelection instanceof MainCorpus)) {
161
	println "Corpora selection is not a Corpus"
162
	return
163
}
164

  
165
// BEGINNING OF PARAMETERS
166
@Field @Option(name="unit_type", usage="", widget="String", required=true, def="MENTION")
167
def unit_type
168
@Field @Option(name="pos_property_name", usage="", widget="String", required=true, def="pos")
169
def pos_property_name
170
@Field @Option(name="reset", usage="", widget="Boolean", required=true, def="true")
171
def reset
172
if (!ParametersDialog.open(this)) return
173

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

  
190
CATEGORIE = "CATEGORIE"
191
// Si la structure d'annotation ne contient pas CATEGORIE, on la crée avec ses valeurs
192
if (!structure.getUniteProperties(unit_type).contains(CATEGORIE)) { 
193

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

  
199
// la propriété
200
	structure.ajouterProp(Unite.class, unit_type, CATEGORIE)
201
// les valeurs
202
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "GN")
203
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "POSS")
204
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PRO")
205
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_O")
206
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_S")
207
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_CL_R")
208
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_REL")
209
	structure.ajouterVal(Unite.class, unit_type, CATEGORIE, "PR_WH")
210
//...
211
}
212

  
213
def nModified = 0
214
def nIgnored = 0
215

  
216
errors = new HashMap()
217
def units = analecCorpus.getUnites(unit_type)
218
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
219
for (Unite unit : units) { // process all units
220
	
221
	def prop = unit.getProp(CATEGORIE)
222
	if (!reset && prop != null && prop.length() > 0) continue // l'unité a déjà une CATEGORIE
223
	
224
	int[] positions = null
225
	if (unit.getDeb() == unit.getFin()) positions = [unit.getDeb()]
226
	else positions = (unit.getDeb()..unit.getFin())
227
	
228
	def Mention = CQI.cpos2Str(posProperty.getQualifiedName(), positions)
229
	def cat = testRules(positions, Mention)
230

  
231
	if (cat != null) {
232
		// following line in the original script but doesn't work for me:
233
      // vue.setValeurChamp(unit, CATEGORIE, cat)
234
      unit.getProps().put(CATEGORIE, cat)
235
		nModified++
236
	} else {
237
		nIgnored++
238
	}
239
}
240

  
241
println "Result:"
242
println "- $nModified units of type $unit_type have been modified."
243
println "- $nIgnored units of type $unit_type have not been modified.\n"
244

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

  
250
// udpate the view (also see also
251
// http://forge.cbp.ens-lyon.fr/redmine/issues/2065)
252
URSCorpora.getVue(analecCorpus).retablirVueParDefaut()
tmp/org.txm.analec.rcp/src/org/txm/macro/urs/democrat/CreationChainesMacro.groovy (revision 2065)
1
// Copyright © 2016 ENS de Lyon, CNRS, University of Franche-Comté
2
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
3
// @author mdecorde
4
// STANDARD DECLARATIONS
5
package org.txm.macro.urs.democrat
6

  
7
import org.kohsuke.args4j.*
8
import groovy.transform.Field
9
import org.txm.rcp.swt.widget.parameters.*
10
import org.txm.annotation.urs.*
11
import org.txm.searchengine.cqp.corpus.*
12
import visuAnalec.donnees.Structure;
13
import visuAnalec.elements.Schema
14
import visuAnalec.elements.Unite;
15
import visuAnalec.vue.Vue
16

  
17
if (!(corpusViewSelection instanceof MainCorpus)) {
18
	println "Corpora selection is not a Corpus"
19
	return;
20
}
21

  
22
// BEGINNING OF PARAMETERS
23
@Field @Option(name="unit_type",usage="", widget="String", required=true, def="MENTION")
24
String unit_type
25
@Field @Option(name="ref_property",usage="", widget="String", required=true, def="REF")
26
String ref_property
27
if (!ParametersDialog.open(this)) return;
28

  
29
int nCreated = 0 // count the number of created CHAINE
30
int nUpdated = 0 // count the number of updated CHAINE
31

  
32
MainCorpus corpus = corpusViewSelection
33
def analecCorpus = URSCorpora.getCorpus(corpus); // analec corpus has the same name has the TXM corpus
34
Structure structure = analecCorpus.getStructure()
35
if (!structure.getUnites().contains(unit_type)) { // check if the structure contains the unit_type units
36
	println "Error: corpus structure does not contains unit with name=$unit_type"
37
	return
38
}
39
if (!structure.getSchemas().contains("CHAINE")) { // update the structure if needed
40
	println "Creating the 'CHAINE' schema in the structure"
41
	analecCorpus.ajouterType(Schema.class, "CHAINE")
42
	analecCorpus.ajouterProp(Schema.class, "CHAINE", "REF")
43
	analecCorpus.ajouterProp(Schema.class, "CHAINE", "GENRE")
44
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "GENRE", "INDETERMINABLE")
45
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "GENRE", "FEMININ")
46
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "GENRE", "MASCULIN")
47
	analecCorpus.ajouterProp(Schema.class, "CHAINE", "NOMBRE")
48
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "NOMBRE", "GROUPE_FLOU")
49
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "NOMBRE", "GROUPE_STRICT")
50
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "NOMBRE", "SINGULIER")
51
	analecCorpus.ajouterProp(Schema.class, "CHAINE", "NB MAILLONS")
52
	analecCorpus.ajouterProp(Schema.class, "CHAINE", "TYPE REFERENT")
53
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "UNKNOWN")
54
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "CONCRET_OBJECT")
55
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "ABSTRACT_OBJECT")
56
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "TIME")
57
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "PRODUCT")
58
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "AMOUNT")
59
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "EVENT")
60
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "GPE")
61
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "ORG")
62
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "PERSON")
63
	analecCorpus.ajouterVal(Schema.class, "CHAINE", "TYPE REFERENT", "LIEU")
64
}
65

  
66
def props = structure.getUniteProperties(unit_type)
67
if (!props.contains(ref_property)) { // check the unit_type units have the REF property
68
	println "Error: $unit_type units have no proprerty named '$ref_property'"
69
	return
70
}
71

  
72
// parse the units to build CHAINES
73
def chaines = [:]
74
def units = analecCorpus.getUnites(unit_type)
75
units.sort() { a, b -> a.getDeb() <=> b.getDeb() ?: a.getFin() <=> b.getFin() }
76
for (Unite unit : units) {
77
	def ref = unit.getProp(ref_property)
78
	if (!chaines.containsKey(ref)) {
79
		chaines[ref] = []
80
	}
81
	chaines[ref] << unit
82
}
83

  
84
// update the already existing CHAINES schemas
85
for (Schema schema : analecCorpus.getSchemas("CHAINE")) {
86
	String ref = schema.getProp(ref_property)
87
	if (chaines.containsKey(ref)) { // the CHAINE exists 
88
		// maj des unités de la chaine existante
89
		int size_before = schema.getContenu().size()
90
		for (def unit : chaines[ref]) schema.ajouter(unit) // insert the new units in the hashset
91
		
92
		// Update the CHAINE size
93
		schema.props.put("NB MAILLONS", Integer.toString(schema.contenu.size())) 
94
		
... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.

Formats disponibles : Unified diff