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 |
|
Formats disponibles : Unified diff