root / tmp / org.txm.analec.rcp / src / org / txm / macro / analec / exploit / StructuresIndexMacro.groovy @ 875
History | View | Annotate | Download (18.4 kB)
1 |
package org.txm.macro.analec.exploit
|
---|---|
2 |
// Copyright © 2017 ENS de Lyon, CNRS, University of Franche-Comté
|
3 |
// Licensed under the terms of the GNU General Public License (http://www.gnu.org/licenses)
|
4 |
// @author sheiden
|
5 |
|
6 |
/*
|
7 |
Macro affichant les statistiques de différentes structures d'un corpus
|
8 |
Paramètres de la macro :
|
9 |
- corpus : le corpus sélectionné dans la vue Corpus
|
10 |
- structures : liste des structures à interroger. Séparer les noms par une virgule.
|
11 |
- structProperties : liste des propriétés de structures. Séparer les noms par une virgule.
|
12 |
Il doit y avoir autant de propriétés de structures que de structures indiquées dans le paramètre structures.
|
13 |
Les structures doivent posséder la propriété demandée.
|
14 |
Ce paramètre peut être laissé vide, dans ce cas la colonne 'prop' n'est pas affichée.
|
15 |
- query : requête CQL de sélection de mots exprimée obligatoirement en format complet : [...]
|
16 |
Par exemple :
|
17 |
- [frpos="N.*"] pour sélectionner les noms communs et les noms propres
|
18 |
- [] pour sélectionner tous les mots
|
19 |
- wordProperty : propriété de mot utilisée pour calculer le vocabulaire et les fréquences
|
20 |
- displayIndex : calculer l'index hiérarchique des valeurs de la propriété wordProperty pour la requête query sur chaque structure
|
21 |
- Vmax : nombre maximum des mots les plus fréquents à afficher dans l'index
|
22 |
Résultat :
|
23 |
Le résultat est un tableau TSV affiché dans la console.
|
24 |
On peut l'exploiter avec un copier/coller dans Calc.
|
25 |
Chaque ligne correspond à une structure du corpus.
|
26 |
Les lignes sont ordonnées par ordre hiérarchique des structures du début à la fin du corpus.
|
27 |
Les colonnes sont :
|
28 |
- struct : nom de la structure
|
29 |
- prop : valeur de la propriété de la structure
|
30 |
(si le paramètre structProperties est vide, cette colonne est absente du résultat)
|
31 |
- start : position du premier mot de la structure dans le corpus
|
32 |
(les positions du corpus sont numérotées à partir de 0).
|
33 |
Les colonnes start et end sont pratiques quand on n'a pas de propriété de structure à afficher pour se repérer dans le corpus.
|
34 |
- end : position du dernier mot de la structure
|
35 |
- T : taille de la structure (end-start)
|
36 |
- t : nombre de mots sélectionnés dans la structure
|
37 |
- v : nombre de valeurs différentes de la propriété des mots sélectionnés dans la structure
|
38 |
- fmin : fréquence minimale des valeurs de la propriété de mots sélectionnés dans la structure
|
39 |
- fmax : fréquence maximale des valeurs de la propriété de mots sélectionnés dans la structure
|
40 |
- index : l'index hiérarchique des valeurs de la propriété de mot choisie des mots sélectionnés par la requête CQL
|
41 |
Exemple de résultats sur le texte "Essais sur la peinture" de Diderot :
|
42 |
struct prop start end T t v fmin fmax index
|
43 |
text DiderotEssais 46203 56871 10668 2011 903 1 38 [nature, couleur, homme, tableau, lumière, objets, œil, toile, art, effet, corps, artiste, ombre, ombres, deux, peintre, peinture, dessin, couleurs, tête]
|
44 |
div 0 46214 49223 3009 549 327 1 16 [nature, homme, modèle, figure, deux, école, artiste, chose, âge, figures, dessin, actions, fois, professeur, action, attitude, manière, femme, col, tête]
|
45 |
p 0 46220 46259 39 5 5 1 1 [nature, forme, cause, êtres, un]
|
46 |
p 1 46260 46456 196 36 25 1 3 [yeux, col, épaules, gorge, femme, jeunesse, nature, accroissement, orbe, paupières, cavité, absence, organe, sourcils, joues, lèvre, mouvement, altération, parties, visage]
|
47 |
p 2 46457 46578 121 28 26 1 2 [pieds, nature, regards, homme, dos, poitrine, forme, cartilages, col, vertèbres, tête, mains, articulation, poignet, coudes, arrière, membres, centre, gravité, système]
|
48 |
p 3 46579 46622 43 5 4 1 2 [causes, effets, êtres, imitation]
|
49 |
p 4 46623 46727 104 22 20 1 2 [ignorance, règles, effets, causes, convention, suites, peine, artiste, imitation, nature, pieds, jambes, genoux, têtes, tact, observation, phénomènes, liaison, enchaînement, difformités]
|
50 |
p 5 46728 46797 69 10 6 1 4 [nez, Antinoüs, nature, difformité, altérations, reste]
|
51 |
p 6 46798 46859 61 9 7 1 2 [règles, nature, homme, rue, chose, statue, proportions]
|
52 |
p 7 46860 46942 82 13 11 1 2 [extrémité, pied, voile, bossu, Venus, Medicis, nature, figure, crayons, monstre, chose]
|
53 |
p 8 46943 46982 39 11 11 1 1 [figure, système, suites, inconséquence, principe, production, art, mille, lieues, œuvre, nature]
|
54 |
p 9 46983 47196 213 38 30 1 5 [homme, figure, âge, fonctions, mystères, art, artiste, proportions, despotisme, nature, condition, sacrifice, cent, manières, organisation, habitude, facilité, grandeur, proportion, membre]
|
55 |
... [13 paragraphes] ...
|
56 |
div 1 49224 52163 2939 531 307 1 23 [couleur, nature, chair, artiste, toile, art, homme, yeux, œil, couleurs, tableau, harmonie, effet, dessin, palette, organe, ton, coloriste, vie, ami]
|
57 |
p 24 49230 49258 28 7 7 1 1 [C', dessin, forme, êtres, couleur, vie, souffle]
|
58 |
p 25 49259 49284 25 6 6 1 1 [maîtres, art, juges, dessin, monde, couleur]
|
59 |
p 26 49285 49354 69 16 16 1 1 [dessinateurs, coloristes, littérature, Cent, froids, orateur, Dix, orateurs, poète, intérêt, homme, Helvétius, dix, bons, peine, mort]
|
60 |
p 27 49355 49485 130 24 21 1 2 [artiste, besoin, échelle, ami, atelier, teintes, demi-, palette, quart, heure, travail, ordre, pendant, passage, auteur, bureau, ligne, livre, place, allure]
|
61 |
p 28 49486 49680 194 46 42 1 2 [yeux, toile, chaos, œuvre, sentiment, couleur, bouche, palette, image, pinceau, création, oiseaux, nuances, plumage, fleurs, velouté, arbres, verdures, azur, ciel]
|
62 |
p 29 49681 49967 286 48 43 1 3 [nature, organe, homme, arbre, artistes, chose, monde, variété, coloristes, couleur, disposition, doute, œil, couleurs, tableau, effets, rouges, blancs, tapisserie, murs]
|
63 |
p 30 49968 50068 100 20 17 1 3 [fois, organe, peintre, ouvrage, littérateur, caractère, disposition, pente, homme, voix, explosion, état, silence, artiste, tableau, couleur, coloris]
|
64 |
p 31 50069 50105 36 7 7 1 1 [coup, organe, affection, corps, vapeur, nature, imitation]
|
65 |
p 32 50106 50267 161 26 19 1 4 [couleur, palette, artiste, effet, tableau, teintes, couleurs, idée, endroit, fois, appréciation, scène, composition, manie, travail, teinte, composé, substances, unes]
|
66 |
p 33 50268 50319 51 7 7 1 1 [général, harmonie, composition, peintre, effet, pinceau, couleur]
|
67 |
... [etc.]
|
68 |
Avec les paramètres :
|
69 |
- structures : text,div,p
|
70 |
- structProperties : id,n,n
|
71 |
- query : [frpos="N.*"]
|
72 |
- wordProperty : word
|
73 |
- displayIndex : true
|
74 |
- Vmax : 20
|
75 |
*/
|
76 |
|
77 |
// Déclarations
|
78 |
|
79 |
import org.kohsuke.args4j.* |
80 |
|
81 |
import groovy.transform.Field |
82 |
|
83 |
import org.txm.rcp.swt.widget.parameters.* |
84 |
import org.txm.Toolbox |
85 |
import org.eclipse.ui.console.* |
86 |
import org.txm.macro.cqp.* |
87 |
import org.txm.searchengine.cqp.corpus.Corpus |
88 |
import org.txm.searchengine.cqp.corpus.Partition |
89 |
import org.txm.searchengine.cqp.corpus.Property |
90 |
import org.txm.searchengine.cqp.corpus.QueryResult |
91 |
import org.txm.searchengine.cqp.corpus.Subcorpus; |
92 |
import org.txm.searchengine.cqp.corpus.query.Query |
93 |
import org.txm.rcp.commands.* |
94 |
|
95 |
byte CQI_CONST_FIELD_MATCH = (byte) 0x10 |
96 |
|
97 |
def scriptName = this.class.getSimpleName() |
98 |
|
99 |
def selection = [] |
100 |
for (def s : corpusViewSelections) { |
101 |
if (s instanceof Corpus) selection << s |
102 |
else if (s instanceof Partition) selection.addAll(s.getParts()) |
103 |
} |
104 |
|
105 |
if (selection.size() == 0) { |
106 |
println "** $scriptName: please select a Corpus or a Partition in the Corpus view: "+corpusViewSelections
|
107 |
return false |
108 |
} |
109 |
println "WORKING WITH $selection"
|
110 |
// BEGINNING OF PARAMETERS
|
111 |
|
112 |
@Field @Option(name="structures", usage="act,scene", widget="String", required=true, def="text,div,p") |
113 |
def structures
|
114 |
@Field @Option(name="structProperties", usage="n,n", widget="String", required=false, def="id,n,n") |
115 |
def structProperties
|
116 |
@Field @Option(name="query", usage="[word!='\\p{P}']", widget="String", required=true, def="[pos=\"NOM.*\"|frpos=\"N.*\"]") |
117 |
def query
|
118 |
@Field @Option(name="wordProperty", usage="word", widget="String", required=true, def="word") |
119 |
def wordProperty
|
120 |
@Field @Option(name="displayIndex", usage="display a hierarchical index", widget="Boolean", required=true, def="true") |
121 |
def displayIndex
|
122 |
@Field @Option(name="Vmax", usage="size of index", widget="Integer", required=false, def="20") |
123 |
def Vmax
|
124 |
// END OF PARAMETERS
|
125 |
|
126 |
// Open the parameters input dialog box
|
127 |
if (!ParametersDialog.open(this)) return; |
128 |
|
129 |
def CQI = CQPSearchEngine.getCqiClient()
|
130 |
|
131 |
def corpusStructs = structures.split(",") // ["act", "scene"] |
132 |
structProperties = structProperties.trim() |
133 |
|
134 |
if (structProperties.size() > 0) { |
135 |
propParam = true
|
136 |
corpusStructPropNames = structProperties.split(",") // ["n", "n"] |
137 |
corpusStructProps = [corpusStructs, corpusStructPropNames].transpose().collectEntries() |
138 |
} else {
|
139 |
propParam = false
|
140 |
} |
141 |
|
142 |
// First define the order theory over corpus structures intervals
|
143 |
// by defining a binary comparator that will be used to build the
|
144 |
// TreeSet of intervals
|
145 |
|
146 |
// function to print the hierarchical index of a query
|
147 |
def print_index = { c, q, p, cut ->
|
148 |
|
149 |
QueryResult qr = c.query(new Query(q), "RES1", false); |
150 |
Subcorpus subcorpus = c.createSubcorpus("RES1", qr);
|
151 |
p = subcorpus.getProperty(p) |
152 |
def tC = subcorpus.getSize()
|
153 |
def matches_target_p = CQI.cpos2Str(p.getQualifiedName(), CQI.dumpSubCorpus(qr.getQualifiedCqpId(), CQI_CONST_FIELD_MATCH, 0, tC-1)) |
154 |
if (cut > 0) { |
155 |
println matches_target_p.countBy { it }.sort { -it.value }.take(cut) |
156 |
} else {
|
157 |
println matches_target_p.countBy { it }.sort { -it.value } |
158 |
} |
159 |
subcorpus.delete() |
160 |
} |
161 |
|
162 |
// function to print the statistics of an index of a query
|
163 |
def print_freq = { Corpus c, q, p ->
|
164 |
|
165 |
// appel du moteur
|
166 |
//println "QUERY=$q"
|
167 |
QueryResult qr = c.query(new Query(q), "RES1", false); |
168 |
Subcorpus subcorpus = c.createSubcorpus("RES1", qr);
|
169 |
p = subcorpus.getProperty(p) |
170 |
int csize = c.getSize()
|
171 |
if (csize == 0) { |
172 |
if (displayIndex) {
|
173 |
println "0\t0\t0\t0\t[]"
|
174 |
} else {
|
175 |
println "0\t0\t0\t0"
|
176 |
} |
177 |
} else {
|
178 |
def tC = CQI.subCorpusSize(subcorpus.getQualifiedCqpId())
|
179 |
def matches_target_p = CQI.cpos2Id(p.getQualifiedName(), CQI.dumpSubCorpus(subcorpus.getQualifiedCqpId(), CQI_CONST_FIELD_MATCH, 0, tC-1)) |
180 |
|
181 |
//println ""
|
182 |
|
183 |
// afficher les positions de mots du résultat
|
184 |
//println CQI.dumpSubCorpus("${c}:RES1", CQI_CONST_FIELD_MATCH, 0, CQI.subCorpusSize("${c}:RES1")-1)
|
185 |
|
186 |
// afficher les codes des occurrences de la propriété du résultat
|
187 |
//println matches_target_p
|
188 |
|
189 |
// afficher l'index hiérarchique des codes du résultat
|
190 |
//println matches_target_p.collect { it }.countBy { it }.sort { -it.value }
|
191 |
|
192 |
// calculer la fréquence de chaque valeur et ne garder que les fréquences
|
193 |
def index = matches_target_p.collect { it }.countBy { it } |
194 |
def freqs = index.values()
|
195 |
|
196 |
// afficher la liste décroissante des fréquences du résultat
|
197 |
//println freqs.sort { -it.value }
|
198 |
|
199 |
|
200 |
//def tF = freqs.sum() // control value
|
201 |
def v = freqs.size()
|
202 |
def fmin = freqs.min()
|
203 |
def fmax = freqs.max()
|
204 |
//println sprintf("t %d, v %d, fmin %d, fmax %d", tC, v, fmin, fmax)
|
205 |
print sprintf("%d\t%d\t%d\t%d", tC, v, fmin, fmax)
|
206 |
// afficher les valeurs des occurrences de la propriété du résultat
|
207 |
if (displayIndex) {
|
208 |
heads = index.sort { -it.value }.take(Vmax).keySet()
|
209 |
println "\t"+heads.collect { CQI.id2Str(p.getQualifiedName(), it)[0] } |
210 |
} else {
|
211 |
println ""
|
212 |
} |
213 |
} |
214 |
subcorpus.delete() |
215 |
} |
216 |
|
217 |
def r = RWorkspace.getRWorkspaceInstance()
|
218 |
|
219 |
/**
|
220 |
* group units by CQP match
|
221 |
*
|
222 |
* units are sorted for faster processing
|
223 |
*
|
224 |
* @param allUnites
|
225 |
* @param matches
|
226 |
* @param strict_inclusion
|
227 |
* @return
|
228 |
*/
|
229 |
static def inter(def allUnites, def matches) { |
230 |
//println allUnites.collect() {it -> it[0]}
|
231 |
allUnites = allUnites.sort() { a, b -> a[0] <=> b[0] ?: a[1] <=> b[1] } |
232 |
//println allUnites.collect() {it -> it[0]}
|
233 |
def unitsSize = allUnites.size()
|
234 |
def iCurrentUnit = 0 |
235 |
def selectedUnits = [] |
236 |
|
237 |
def matchesSize = matches.size()
|
238 |
def iCurrentMatch = 0 |
239 |
|
240 |
|
241 |
while (iCurrentMatch < matchesSize && iCurrentUnit < unitsSize) {
|
242 |
|
243 |
def unit = allUnites[iCurrentUnit]
|
244 |
def match = matches[iCurrentMatch]
|
245 |
if (unit[1] < match.getStart()) { |
246 |
iCurrentUnit++ |
247 |
} else if (unit[0] > match.getEnd()) { |
248 |
iCurrentMatch++ |
249 |
} else {
|
250 |
|
251 |
if (match.getStart() <= unit[0] && unit[1] <= match.getEnd()) { |
252 |
selectedUnits << unit |
253 |
} |
254 |
|
255 |
iCurrentUnit++ |
256 |
} |
257 |
} |
258 |
return selectedUnits
|
259 |
} |
260 |
|
261 |
selection.each { corpus -> |
262 |
|
263 |
corpusName = corpus.getName() |
264 |
mainCorpusName = corpus.getMainCorpus().getName() |
265 |
println "Corpus = "+corpusName
|
266 |
println "Corpus QualifiedCqpId = "+corpus.getCqpId()
|
267 |
println "MainCorpus = "+mainCorpusName
|
268 |
println "Corpus QualifiedCqpId = "+corpus.getMainCorpus().getCqpId()
|
269 |
|
270 |
def struct_names = (CQI.corpusStructuralAttributes(corpus.getMainCorpus().getCqpId()) as List) |
271 |
struct_names.removeAll { it.contains('_') } |
272 |
struct_names=(struct_names-"txmcorpus").grep(corpusStructs)
|
273 |
//println "struct_names = "+struct_names
|
274 |
|
275 |
if (struct_names.size() == 0) { |
276 |
println "** Impossible to find the structures (${corpusStructs}), aborting."
|
277 |
return
|
278 |
} |
279 |
|
280 |
def level = [:]
|
281 |
|
282 |
// Now build the TreeSet of corpus structures intervals
|
283 |
|
284 |
def h = new TreeSet<Struct>() |
285 |
|
286 |
struct_names.each { |
287 |
def matches = [] |
288 |
for (i in 0..CQI.attributeSize("${mainCorpusName}.${it}")-1) { |
289 |
(start, end) = CQI.struc2Cpos("${mainCorpusName}.${it}", i)
|
290 |
matches << [start, end] |
291 |
//println sprintf("Adding %s[%d, %d]", it, start, end)
|
292 |
} |
293 |
def intersection = inter(matches, corpus.getMatches())
|
294 |
for (def item : intersection) |
295 |
h.add(new Struct(it, item[0], item[1])) |
296 |
} |
297 |
|
298 |
if (propParam) {
|
299 |
print sprintf("struct\tprop\tstart\tend\tT\tt\tv\tfmin\tfmax")
|
300 |
} else {
|
301 |
print sprintf("struct\tstart\tend\tT\tt\tv\tfmin\tfmax")
|
302 |
} |
303 |
|
304 |
if (displayIndex) {
|
305 |
println sprintf("\tindex")
|
306 |
} else {
|
307 |
println ""
|
308 |
} |
309 |
|
310 |
def env = System.getenv() |
311 |
def localPath = env["HOME"]+"/Documents/d3test" |
312 |
new File(localPath).mkdirs() |
313 |
|
314 |
// reset output file
|
315 |
def resultFile = new File(localPath, "desc-partition.html") |
316 |
def result = new PrintWriter(resultFile) |
317 |
result.print("")
|
318 |
result.close() |
319 |
|
320 |
resultFile << '''\
|
321 |
<!DOCTYPE html>
|
322 |
<html>
|
323 |
<head>
|
324 |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" charset="UTF-8"/>
|
325 |
<link type="text/css" rel="stylesheet" href="style.css"/>
|
326 |
<script type="text/javascript" src="d3/d3.v3.js" charset="utf-8"></script>
|
327 |
<script type="text/javascript" src="d3/layout/partition.js" charset="utf-8"></script>
|
328 |
<style type="text/css">
|
329 |
|
330 |
.chart {
|
331 |
display: block;
|
332 |
margin: auto;
|
333 |
margin-top: 60px;
|
334 |
font-size: 11px;
|
335 |
}
|
336 |
|
337 |
rect {
|
338 |
stroke: #eee;
|
339 |
fill: #aaa;
|
340 |
fill-opacity: .8;
|
341 |
}
|
342 |
|
343 |
rect.parent {
|
344 |
cursor: pointer;
|
345 |
fill: steelblue;
|
346 |
}
|
347 |
|
348 |
text {
|
349 |
pointer-events: none;
|
350 |
}
|
351 |
|
352 |
</style>
|
353 |
</head>
|
354 |
<body>
|
355 |
<div id="body">
|
356 |
<div id="footer">
|
357 |
Structures hierarchy
|
358 |
<div class="hint">click or shift-alt-click to zoom-in or out</div>
|
359 |
</div>
|
360 |
</div>
|
361 |
<script type="text/javascript">
|
362 |
|
363 |
var w = 1120,
|
364 |
h = 600,
|
365 |
x = d3.scale.linear().range([0, w]),
|
366 |
y = d3.scale.linear().range([0, h]);
|
367 |
|
368 |
var vis = d3.select("#body").append("div")
|
369 |
.attr("class", "chart")
|
370 |
.style("width", w + "px")
|
371 |
.style("height", h + "px")
|
372 |
.append("svg:svg")
|
373 |
.attr("width", w)
|
374 |
.attr("height", h);
|
375 |
|
376 |
var partition = d3.layout.partition()
|
377 |
.value(function(d) { return d.size; }).sort(null);
|
378 |
|
379 |
var tree = `{'''
|
380 |
|
381 |
// Now iterate on the TreeSet to get a depth first search on the structure intervals
|
382 |
|
383 |
def rec_struct_regex = /([^0-9]+)[0-9]+/ |
384 |
|
385 |
/*
|
386 |
"name": "sha-hamlet",
|
387 |
"children": [
|
388 |
{
|
389 |
"name": "sha-hamcast",
|
390 |
"children": [
|
391 |
{
|
392 |
"name": "sha-ham1",
|
393 |
"children": [
|
394 |
{"name": "sha-ham102", "size": 855},
|
395 |
{"name": "sha-ham103", "size": 464},
|
396 |
{"name": "sha-ham104", "size": 296},
|
397 |
{"name": "sha-ham105", "size": 635}
|
398 |
]
|
399 |
}
|
400 |
]
|
401 |
}
|
402 |
]
|
403 |
}`;
|
404 |
*/
|
405 |
|
406 |
def displayTree = { head ->
|
407 |
if (head) {
|
408 |
subtree = h.tailSet(head) |
409 |
subtree.each { print sprintf("%s[%d, %d], ", it.name, it.start, it.end) } |
410 |
println ""
|
411 |
if (subtree.size() == 0) { |
412 |
println sprintf("%s[%d, %d]", head.name, head.start, head.end)
|
413 |
} else {
|
414 |
displayTree(subtree) |
415 |
} |
416 |
} |
417 |
} |
418 |
|
419 |
//displayTree(h.first())
|
420 |
|
421 |
def divPropVals = [] |
422 |
def divLengths = [] |
423 |
def textDivPropVals = [] |
424 |
def textDivLengths = [] |
425 |
|
426 |
h.each { |
427 |
|
428 |
//println sprintf("Displaying %s[%d, %d]", it.name, it.start, it.end)
|
429 |
if (propParam) {
|
430 |
|
431 |
def rec_match = (it.name =~ rec_struct_regex) |
432 |
if (rec_match.size() == 1) { |
433 |
println "Rec struct match = "+rec_match[0][1] |
434 |
istruct_name = rec_match[0][1] |
435 |
} else {
|
436 |
//println "Struct match = "+it.name
|
437 |
istruct_name = it.name
|
438 |
} |
439 |
|
440 |
def struct_name = "${mainCorpusName}.${istruct_name}_${corpusStructProps[it.name]}" |
441 |
def propVal = CQI.struc2Str(struct_name, CQI.cpos2Struc(struct_name, [it.start] as int[]))[0] |
442 |
if (it.name == "text") { |
443 |
textDivPropVals.push(divPropVals) |
444 |
divPropVals = []
|
445 |
textDivLengths.push(divLengths) |
446 |
divLengths = []
|
447 |
} else if (it.name == "div") { |
448 |
divPropVals.push(propVal) |
449 |
divLengths.push(it.end-it.start) |
450 |
} |
451 |
|
452 |
|
453 |
print sprintf("%s\t%s\t%d\t%d\t%d\t", it.name, propVal, it.start, it.end, it.end-it.start) |
454 |
} else {
|
455 |
def struct_name = "${mainCorpusName}.${it.name}" |
456 |
print sprintf("%s\t%d\t%d\t%d\t", it.name, it.start, it.end, it.end-it.start) |
457 |
} |
458 |
print_freq(corpus, sprintf("a:%s :: a>=%d & a<=%d", query, it.start, it.end), wordProperty) |
459 |
} |
460 |
|
461 |
textDivPropVals.push(divPropVals) |
462 |
textDivPropVals.remove(0)
|
463 |
textDivLengths.push(divLengths) |
464 |
textDivLengths.remove(0)
|
465 |
|
466 |
println textDivPropVals |
467 |
println textDivLengths |
468 |
|
469 |
def textDivPropVals1 = textDivPropVals[0] as String[] |
470 |
r.addVectorToWorkspace("textDivPropVals1", textDivPropVals1)
|
471 |
def textDivLengths1 = textDivLengths[0] as int[] |
472 |
r.addVectorToWorkspace("textDivLengths1", textDivLengths1)
|
473 |
|
474 |
def PNGFile = File.createTempFile("txm", ".png", new File(Toolbox.getTxmHomePath(), "results")) |
475 |
def PNGFilePath = PNGFile.getAbsolutePath()
|
476 |
println "PNG file: "+PNGFilePath
|
477 |
|
478 |
def SVGFile = File.createTempFile("txm", ".svg", new File(Toolbox.getTxmHomePath(), "results")) |
479 |
def SVGFilePath = SVGFile.getAbsolutePath()
|
480 |
println "SVG file: "+SVGFilePath
|
481 |
|
482 |
/// BEGINNING OF R SCRIPT
|
483 |
def script =""" |
484 |
df <- data.frame(structure=textDivPropVals1,
|
485 |
longueur=textDivLengths1)
|
486 |
p<-ggplot(data=df, aes(x=structure, y=longueur)) +
|
487 |
geom_bar(stat="identity", fill="steelblue") +
|
488 |
geom_text(aes(label=longueur), vjust=1.6, color="white", size=3.5) +
|
489 |
labs(title="${corpusName}", x="Structure div", y = "Longueur") +
|
490 |
theme_minimal()
|
491 |
"""
|
492 |
/// END OF R SCRIPT
|
493 |
|
494 |
// execute R script
|
495 |
r.eval("library(ggplot2)")
|
496 |
r.eval(script+"ggsave(file=\"${PNGFilePath}\", plot=p)")
|
497 |
r.eval(script+"ggsave(file=\"${SVGFilePath}\", plot=p)")
|
498 |
|
499 |
//display the SVG results graphic
|
500 |
monitor.syncExec(new Runnable() { |
501 |
@Override
|
502 |
public void run() { try { OpenSVGGraph.OpenSVGFile(SVGFilePath, "Longueur des structures de "+corpusName) } catch(Exception e) {e.printStackTrace()} } |
503 |
}) |
504 |
|
505 |
} |
506 |
|