Révision 3555
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/export/office/SetOfficeMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
package org.txm.macro.office |
|
3 |
|
|
4 |
import org.kohsuke.args4j.* |
|
5 |
import groovy.transform.Field |
|
6 |
import org.txm.rcp.swt.widget.parameters.* |
|
7 |
|
|
8 |
// BEGINNING OF PARAMETERS |
|
9 |
|
|
10 |
@Field @Option(name="office_path", usage="Path to LibreOffice or OpenOffice installation directory", widget="Folder", required=false, def="libreoffice or openoffice install directory") |
|
11 |
def office_path |
|
12 |
|
|
13 |
// Open the parameters input dialog box |
|
14 |
if (!ParametersDialog.open(this)) return; |
|
15 |
|
|
16 |
// END OF PARAMETERS |
|
17 |
|
|
18 |
if (office_path == null) { |
|
19 |
println "No path to office directory given." |
|
20 |
return |
|
21 |
} |
|
22 |
|
|
23 |
if (!office_path.exists()) { |
|
24 |
println "'$office_path' directory not found." |
|
25 |
return |
|
26 |
} |
|
27 |
|
|
28 |
if (!office_path.isDirectory()) { |
|
29 |
println "'$office_path' exists but is not a directory." |
|
30 |
return |
|
31 |
} |
|
32 |
|
|
33 |
if (!office_path.canExecute()) { |
|
34 |
println "'$office_path' exists but has not sufficent rights to be used." |
|
35 |
return |
|
36 |
} |
|
37 |
|
|
38 |
def old = System.getProperty("office.home") |
|
39 |
System.setProperty("office.home", office_path.getAbsolutePath()) |
|
40 |
println "Office path set to '"+System.getProperty("office.home")+"'." |
|
41 |
if (old != null) { |
|
42 |
println " Previous path was '${old}'." |
|
43 |
} |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/export/office/MergeExcelDirMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// Copyright © 2019 ENS de Lyon, CNRS, University of Franche-Comté |
|
2 |
// @author mdecorde |
|
3 |
// @author sheiden |
|
4 |
|
|
5 |
package org.txm.macro.office |
|
6 |
|
|
7 |
import org.kohsuke.args4j.* |
|
8 |
import groovy.transform.Field |
|
9 |
import java.nio.charset.Charset |
|
10 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
11 |
import org.txm.utils.* |
|
12 |
import javax.xml.stream.* |
|
13 |
import java.net.URL |
|
14 |
|
|
15 |
import org.apache.poi.ss.usermodel.* |
|
16 |
import org.apache.poi.hssf.usermodel.* |
|
17 |
import org.apache.poi.xssf.usermodel.* |
|
18 |
import org.apache.poi.ss.util.* |
|
19 |
|
|
20 |
@Field @Option(name="inputDirectory", usage="dossier des fichiers Excel à fusionner", widget="Folder", required=true, def="") |
|
21 |
def inputDirectory |
|
22 |
|
|
23 |
@Field @Option(name="outputFile", usage="output file", widget="FileSave", required=true, def="") |
|
24 |
def outputFile |
|
25 |
|
|
26 |
@Field @Option(name="sheetName", usage="sheet name (if no name is given the first sheet will be used)", widget="String", required=false, def="") |
|
27 |
def sheetName |
|
28 |
|
|
29 |
@Field @Option(name="columnList", usage="list of columns to extract, separated by comma", widget="String", required=false, def="") |
|
30 |
def columnList |
|
31 |
|
|
32 |
@Field @Option(name="multipleValues", usage="list of columns with multiple values, separated by comma", widget="String", required=false, def="") |
|
33 |
def multipleValues |
|
34 |
|
|
35 |
@Field @Option(name="normalizeIdentifiers", usage="normalize column names to simple lower case letters", widget="Boolean", required=true, def="true") |
|
36 |
def normalizeIdentifiers |
|
37 |
|
|
38 |
def stringToIdent = { str -> org.txm.utils.AsciiUtils.buildAttributeId(org.txm.utils.AsciiUtils.convertNonAscii(str)).toLowerCase() } |
|
39 |
|
|
40 |
if (!ParametersDialog.open(this)) return false |
|
41 |
|
|
42 |
if (!inputDirectory.exists()) { |
|
43 |
println "** $scriptName: no '"+inputDirectory.name+"' directory found. Aborting." |
|
44 |
return false |
|
45 |
} |
|
46 |
|
|
47 |
if (!inputDirectory.canRead()) { |
|
48 |
println "** $scriptName: '"+inputDirectory.name+"' directory not readable. Aborting." |
|
49 |
return false |
|
50 |
} |
|
51 |
|
|
52 |
def aborted = false |
|
53 |
|
|
54 |
def scriptName = this.class.getSimpleName() |
|
55 |
|
|
56 |
columnList = columnList.split(",") as List |
|
57 |
|
|
58 |
println "columnList = "+columnList |
|
59 |
|
|
60 |
multipleValues = multipleValues.split(",") as List |
|
61 |
|
|
62 |
// create output file |
|
63 |
out = new FileOutputStream(outputFile) |
|
64 |
HSSFWorkbook wb = new HSSFWorkbook() |
|
65 |
finalSheet = wb.createSheet() |
|
66 |
|
|
67 |
// create header line |
|
68 |
nFinalRows = 1 |
|
69 |
r = finalSheet.createRow(0) |
|
70 |
columnList.eachWithIndex { columnName, i -> |
|
71 |
c = r.createCell(i) |
|
72 |
c.setCellValue(normalizeIdentifiers?stringToIdent(columnName):columnName) |
|
73 |
} |
|
74 |
|
|
75 |
def f = [] |
|
76 |
|
|
77 |
inputDirectory.eachFileMatch(~/.*\.xlsx/) { f << it } |
|
78 |
|
|
79 |
if (f.size() == 0) { |
|
80 |
println "** $scriptName: no .xlsx file found. Aborting." |
|
81 |
return false |
|
82 |
} |
|
83 |
|
|
84 |
debug = false |
|
85 |
//ConsoleProgressBar cpb = new ConsoleProgressBar(f.size()) |
|
86 |
|
|
87 |
try { |
|
88 |
|
|
89 |
// for each .xlsx input file (lexicographic order) |
|
90 |
f.sort { it.name }.each { inputFile -> |
|
91 |
|
|
92 |
if (aborted) return false |
|
93 |
|
|
94 |
if (debug) println "Processing "+inputFile+"." |
|
95 |
//cpb.tick() |
|
96 |
rownum = 0 |
|
97 |
|
|
98 |
// open input sheet |
|
99 |
wb2 = WorkbookFactory.create(inputFile) |
|
100 |
ws = null |
|
101 |
if (sheetName.length() == 0) { |
|
102 |
ws = wb2.getSheetAt(0) |
|
103 |
} else { |
|
104 |
ws = wb2.getSheet(sheetName) |
|
105 |
if (ws == null) { |
|
106 |
println "** $scriptName: no '"+sheetName+" found. Aborting." |
|
107 |
aborted = true |
|
108 |
return false |
|
109 |
} |
|
110 |
} |
|
111 |
|
|
112 |
if (ws == null) { |
|
113 |
println "** $scriptName: no sheet found. Aborting." |
|
114 |
aborted = true |
|
115 |
return false |
|
116 |
} |
|
117 |
|
|
118 |
nRows = ws.getPhysicalNumberOfRows() |
|
119 |
if (debug) println nRows+" rows." |
|
120 |
|
|
121 |
// get columns positions |
|
122 |
firstRow = ws.getRow(0) |
|
123 |
nCols = firstRow.getPhysicalNumberOfCells() |
|
124 |
def colNames = [] |
|
125 |
def cellIndexes = [] |
|
126 |
def multipleValuesCols = [] |
|
127 |
0.upto(nCols-1, { iCol -> |
|
128 |
value = firstRow.getCell(iCol).getStringCellValue() |
|
129 |
if (columnList.contains(value)) { |
|
130 |
colNames << value |
|
131 |
cellIndexes << iCol |
|
132 |
} |
|
133 |
if (multipleValues.contains(value)) { |
|
134 |
multipleValuesCols << iCol |
|
135 |
} |
|
136 |
}) |
|
137 |
|
|
138 |
if (cellIndexes.size() != columnList.size()) { |
|
139 |
columnList.removeAll(colNames) |
|
140 |
println "** $scriptName: some columns missing in file $inputFile: "+columnList.join(", ")+". Aborting." |
|
141 |
|
|
142 |
aborted = true |
|
143 |
return false |
|
144 |
} |
|
145 |
|
|
146 |
// sort columns indexes by columnList parameter order |
|
147 |
cellIndexes.sort { columnList.indexOf(colNames[cellIndexes.indexOf(it)]) } |
|
148 |
|
|
149 |
// copy column values |
|
150 |
1.upto(nRows-1, { iRow -> |
|
151 |
row = ws.getRow(iRow) |
|
152 |
r = finalSheet.createRow(nFinalRows) |
|
153 |
|
|
154 |
nCellCreated = 0 |
|
155 |
cellIndexes.each { iCol -> |
|
156 |
value = row.getCell(iCol).getStringCellValue() |
|
157 |
c = r.createCell(nCellCreated) |
|
158 |
if (iCol in multipleValuesCols && value.size() > 0) { |
|
159 |
(lstr = value.split(";")*.trim() as List).removeAll { it.isEmpty() } |
|
160 |
c.setCellValue("|"+lstr.join("|")+"|") |
|
161 |
} else { |
|
162 |
c.setCellValue(value) |
|
163 |
} |
|
164 |
nCellCreated++ |
|
165 |
} |
|
166 |
|
|
167 |
nFinalRows++ |
|
168 |
}) |
|
169 |
} |
|
170 |
} catch(Exception e) { |
|
171 |
aborted = true |
|
172 |
return false |
|
173 |
} |
|
174 |
//cpb.done() |
|
175 |
|
|
176 |
/* write sheet */ |
|
177 |
|
|
178 |
wb.write(out) |
|
179 |
out.close() |
|
180 |
|
|
181 |
if (aborted) return false |
|
182 |
|
|
183 |
println nFinalRows+" rows written." |
|
184 |
|
|
185 |
return true |
|
186 |
|
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/CAStyleMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
// @author mdecorde sjacquot sheiden |
|
3 |
package org.txm.macro |
|
4 |
|
|
5 |
import org.kohsuke.args4j.* |
|
6 |
import groovy.transform.Field |
|
7 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
8 |
import org.txm.searchengine.cqp.clientExceptions.* |
|
9 |
import org.txm.searchengine.cqp.corpus.* |
|
10 |
import org.txm.searchengine.cqp.corpus.query.* |
|
11 |
import org.apache.commons.lang.time.StopWatch |
|
12 |
import java.util.Arrays |
|
13 |
import org.jfree.chart.renderer.xy.* |
|
14 |
import org.jfree.chart.renderer.* |
|
15 |
import org.jfree.chart.plot.* |
|
16 |
import org.jfree.data.xy.* |
|
17 |
import org.jfree.chart.axis.* |
|
18 |
import java.awt.*; |
|
19 |
import java.awt.geom.*; |
|
20 |
import org.jfree.chart.labels.* |
|
21 |
|
|
22 |
import org.txm.ca.core.functions.CA |
|
23 |
import org.txm.ca.core.chartsengine.jfreechart.themes.highcharts.renderers.* |
|
24 |
import org.txm.ca.rcp.editors.* |
|
25 |
import org.txm.libs.office.ReadODS |
|
26 |
import org.txm.ca.core.chartsengine.jfreechart.datasets.* |
|
27 |
import org.jfree.chart.renderer.AbstractRenderer |
|
28 |
import java.awt.geom.Ellipse2D |
|
29 |
import org.jfree.chart.util.ShapeUtils |
|
30 |
|
|
31 |
|
|
32 |
println "editor: "+editor |
|
33 |
|
|
34 |
if (!(editor instanceof CAEditor)) { |
|
35 |
println "editor is not a CA editor: $editor, Run the macro with F12 when the editor is selected :-)" |
|
36 |
return |
|
37 |
} |
|
38 |
|
|
39 |
@Field @Option(name="patternsODSFile", usage="The starting word", widget="FileOpen", required=true, def='patterns.ods') |
|
40 |
def patternsODSFile |
|
41 |
@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF ON ALL REALLY ALL", required=true, def="OFF") |
|
42 |
debug |
|
43 |
|
|
44 |
// Open the parameters input dialog box |
|
45 |
if (!ParametersDialog.open(this)) return; |
|
46 |
if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3 |
|
47 |
|
|
48 |
if (!patternsODSFile.exists()) { |
|
49 |
println "Pattern file not found: $patternsODSFile" |
|
50 |
return false; |
|
51 |
} |
|
52 |
if (!patternsODSFile.isFile() || !patternsODSFile.getName().toLowerCase().endsWith(".ods")) { |
|
53 |
println "Wrong pattern file: $patternsODSFile" |
|
54 |
return false; |
|
55 |
} |
|
56 |
|
|
57 |
def data = ReadODS.toTable(patternsODSFile, "rows") |
|
58 |
def keys = data[0] |
|
59 |
def row_styles = [:] // reformat data |
|
60 |
for (int i = 1 ; i < data.size() ; i++) { |
|
61 |
def h = data[i] |
|
62 |
def style = [:] // create style entry |
|
63 |
String s = h[0]; |
|
64 |
row_styles[/$s/] = style // with a regexp pattern as key |
|
65 |
|
|
66 |
// fill the style |
|
67 |
for (int j = 1 ; j < h.size() ; j++) { |
|
68 |
style[keys[j]] = h[j] |
|
69 |
} |
|
70 |
} |
|
71 |
if (debug > 0) { |
|
72 |
println "ROW STYLES=$row_styles" |
|
73 |
} |
|
74 |
|
|
75 |
data = ReadODS.toTable(patternsODSFile, "cols") |
|
76 |
keys = data[0] |
|
77 |
def col_styles = [:] // reformat data |
|
78 |
|
|
79 |
for (int i = 1 ; i < data.size() ; i++) { |
|
80 |
def h = data[i] |
|
81 |
def style = [:] // create style entry |
|
82 |
String s = h[0]; |
|
83 |
col_styles[/$s/] = style // with a regexp pattern as key |
|
84 |
|
|
85 |
// fill the style |
|
86 |
for (int j = 1 ; j < h.size() ; j++) { |
|
87 |
style[keys[j]] = h[j] |
|
88 |
} |
|
89 |
} |
|
90 |
if (debug > 0) { |
|
91 |
println "COL STYLES=$col_styles" |
|
92 |
} |
|
93 |
|
|
94 |
ica = editor.getCA() |
|
95 |
ca = ica.getCA() |
|
96 |
|
|
97 |
// http://txm.sourceforge.net/javadoc/TXM/TBX/org/txm/stat/engine/r/function/CA.html |
|
98 |
|
|
99 |
// SOME DATA |
|
100 |
rows = ica.getRowNames() |
|
101 |
rowsinfo = ica.getRowInfos() |
|
102 |
rowscos2 = ca.getRowCos2() |
|
103 |
cols = ica.getColNames() |
|
104 |
colssinfo = ica.getColInfos() |
|
105 |
colscos2 = ca.getColCos2() |
|
106 |
D1 = ica.getFirstDimension() -1; |
|
107 |
D2 = ica.getSecondDimension() -1; |
|
108 |
|
|
109 |
// create some AWT shapes for replacement |
|
110 |
shapes = new HashMap<String, Shape>(); |
|
111 |
// dimensions scaling factor (the same used in default theme for the replaced shapes have same dimension than non-replaced) |
|
112 |
float itemShapesScalingFactor = 1.2f |
|
113 |
shapes["diamond"] = ShapeUtils.createDiamond((float)(itemShapesScalingFactor * 3.4f)); |
|
114 |
shapes["square"] = AbstractRenderer.DEFAULT_SHAPE; |
|
115 |
|
|
116 |
float circleSize = 6.4f * itemShapesScalingFactor; |
|
117 |
shapes["disk"] = new Ellipse2D.Float((float)(-circleSize / 2), (float)(-circleSize / 2), circleSize, circleSize); |
|
118 |
|
|
119 |
shapes["triangle"] = ShapeUtils.createUpTriangle((float)(itemShapesScalingFactor * 3.2f)); |
|
120 |
|
|
121 |
//shapes["star"] = AbstractRenderer.DEFAULT_SHAPE; |
|
122 |
//shapes["circle"] = AbstractRenderer.DEFAULT_SHAPE; |
|
123 |
|
|
124 |
|
|
125 |
println "SHAPES=$shapes" |
|
126 |
|
|
127 |
|
|
128 |
// styles per col index in dataset |
|
129 |
// set col label |
|
130 |
colLabelStyle = new HashMap<Integer, String>(); |
|
131 |
// set col visibility |
|
132 |
colHiddenStyle = new HashSet<Integer>(); // true false |
|
133 |
// set col font size |
|
134 |
colFontSizeStyle = new HashMap<Integer, Float>(); |
|
135 |
// set col font color |
|
136 |
colFontColorStyle = new HashMap<Integer, Color>(); |
|
137 |
// set col font family |
|
138 |
colFontFamilyStyle = new HashMap<Integer, String>(); |
|
139 |
// set col points size |
|
140 |
colPointSizeStyle = new HashMap<Integer, Double>(); |
|
141 |
// set col points RGBA color |
|
142 |
colPointColorStyle = new HashMap<Integer, Color>(); |
|
143 |
// set col points shape (circle, square, triangle, ... + color ? + size ?) -> expert |
|
144 |
colPointShapeStyle = new HashMap<Integer, Shape>(); // circle, square, triangle, etc. |
|
145 |
// set col font style (1 = bold, 2 = italic, 3 = bold + italic) |
|
146 |
colFontStyleStyle = new HashMap<Integer, Integer>(); |
|
147 |
|
|
148 |
|
|
149 |
// set row label |
|
150 |
rowLabelStyle = new HashMap<Integer, String>(); |
|
151 |
// set row visibility |
|
152 |
rowHiddenStyle = new HashSet<Integer>(); // true false |
|
153 |
// set row font size |
|
154 |
rowFontSizeStyle = new HashMap<Integer, Float>(); |
|
155 |
// set row font size |
|
156 |
rowFontColorStyle = new HashMap<Integer, Color>(); |
|
157 |
// set row font size |
|
158 |
rowFontFamilyStyle = new HashMap<Integer, String>(); |
|
159 |
// set row points size |
|
160 |
rowPointSizeStyle = new HashMap<Integer, Double>(); |
|
161 |
// set row points RGBA color |
|
162 |
rowPointColorStyle = new HashMap<Integer, Color>(); |
|
163 |
// set row points shape (circle, square, triangle, ... + color ? + size ?) -> expert |
|
164 |
rowPointShapeStyle = new HashMap<Integer, Shape>(); // circle, square, triangle, etc. |
|
165 |
// set row font style (1 = bold, 2 = italic, 3 = bold + italic) |
|
166 |
rowFontStyleStyle = new HashMap<Integer, Integer>(); |
|
167 |
|
|
168 |
// prepare col style data for the dataset |
|
169 |
for (int i = 0 ; i < cols.length ; i++) { |
|
170 |
for (def p : col_styles.keySet()) { |
|
171 |
if (cols[i] ==~ p) { |
|
172 |
def style = col_styles[p] |
|
173 |
if (style["label-replacement"] != null && style["label-replacement"].length() > 0) { |
|
174 |
colLabelStyle[i] = style["label-replacement"] |
|
175 |
} |
|
176 |
if (style["hidden"] != null && style["hidden"].toUpperCase() == "T") { |
|
177 |
colHiddenStyle << i |
|
178 |
} |
|
179 |
if (style["shape-size"] != null && style["shape-size"].length() > 0) { |
|
180 |
colPointSizeStyle[i] = Double.parseDouble(style["shape-size"]) |
|
181 |
} |
|
182 |
if (style["shape-color"] != null && style["shape-color"].length() > 0 ) { |
|
183 |
colPointColorStyle[i] = rgbaStringToColor(style["shape-color"]) |
|
184 |
} |
|
185 |
if (style["shape-replacement"] != null && shapes.containsKey(style["shape-replacement"])) { |
|
186 |
colPointShapeStyle[i] = shapes[style["shape-replacement"]] |
|
187 |
} |
|
188 |
if (style["label-size"] != null && style["label-size"].length() > 0) { |
|
189 |
colFontSizeStyle[i] = Float.parseFloat(style["label-size"]) |
|
190 |
} |
|
191 |
if (style["label-color"] != null && style["label-color"].length() > 0) { |
|
192 |
colFontColorStyle[i] = rgbaStringToColor(style["label-color"]) |
|
193 |
} |
|
194 |
if (style["label-font-family"] != null && style["label-font-family"].length() > 0) { |
|
195 |
colFontFamilyStyle[i] = style["label-font-family"] |
|
196 |
} |
|
197 |
if (style["label-style"] != null && style["label-style"].length() > 0) { |
|
198 |
colFontStyleStyle[i] = Integer.parseInt(style["label-style"]) |
|
199 |
} |
|
200 |
|
|
201 |
} |
|
202 |
} |
|
203 |
} |
|
204 |
if (debug > 0) { |
|
205 |
println "COL COL=$colPointColorStyle" |
|
206 |
println "COL SHP=$colPointShapeStyle" |
|
207 |
println "COL LAB=$colLabelStyle" |
|
208 |
println "COL FONT-SIZ=$colFontSizeStyle" |
|
209 |
println "COL SIZ=$colPointSizeStyle" |
|
210 |
println "COL VIZ=$colHiddenStyle" |
|
211 |
println "COL STYLE=$colFontStyleStyle" |
|
212 |
} |
|
213 |
|
|
214 |
// prepare row style data for the dataset |
|
215 |
for (int i = 0 ; i < rows.length ; i++) { |
|
216 |
for (def p : row_styles.keySet()) { |
|
217 |
if (rows[i] ==~ p) { |
|
218 |
def style = row_styles[p] |
|
219 |
if (style["hidden"] != null && style["hidden"].toUpperCase() == "T") { |
|
220 |
rowHiddenStyle << i |
|
221 |
} |
|
222 |
if (style["label-replacement"] != null && style["label-replacement"].length() > 0) { |
|
223 |
rowLabelStyle[i] = style["label-replacement"] |
|
224 |
} |
|
225 |
if (style["shape-size"] != null && style["shape-size"].length() > 0) { |
|
226 |
rowPointSizeStyle[i] = Double.parseDouble(style["shape-size"]) |
|
227 |
} |
|
228 |
if (style["shape-color"] != null && style["shape-color"].length() > 0 ) { |
|
229 |
rowPointColorStyle[i] = rgbaStringToColor(style["shape-color"]) |
|
230 |
} |
|
231 |
if (style["shape-replacement"] != null && shapes.containsKey(style["shape-replacement"])) { |
|
232 |
rowPointShapeStyle[i] = shapes[style["shape-replacement"]] |
|
233 |
} |
|
234 |
if (style["label-size"] != null && style["label-size"].length() > 0) { |
|
235 |
rowFontSizeStyle[i] = Float.parseFloat(style["label-size"]) |
|
236 |
} |
|
237 |
if (style["label-color"] != null && style["label-color"].length() > 0) { |
|
238 |
rowFontColorStyle[i] = rgbaStringToColor(style["label-color"]) |
|
239 |
} |
|
240 |
if (style["label-font-family"] != null && style["label-font-family"].length() > 0) { |
|
241 |
rowFontFamilyStyle[i] = style["label-font-family"] |
|
242 |
} |
|
243 |
if (style["label-style"] != null && style["label-style"].length() > 0) { |
|
244 |
rowFontStyleStyle[i] = Integer.parseInt(style["label-style"]) |
|
245 |
} |
|
246 |
} |
|
247 |
} |
|
248 |
} |
|
249 |
if (debug > 0) { |
|
250 |
println "ROW COL=$rowPointColorStyle" |
|
251 |
println "ROW SHP=$rowPointShapeStyle" |
|
252 |
println "ROW LAB=$rowLabelStyle" |
|
253 |
println "ROW FONT-SIZ=$rowFontSizeStyle" |
|
254 |
println "ROW SIZ=$rowPointSizeStyle" |
|
255 |
println "ROW VIZ=$rowHiddenStyle" |
|
256 |
println "ROW STYLE=$rowFontStyleStyle" |
|
257 |
} |
|
258 |
|
|
259 |
|
|
260 |
|
|
261 |
// Redefine the chart renderer and update the chart |
|
262 |
def chartEditor = editor.getEditors()[0] |
|
263 |
def chartComposite = chartEditor.getComposite() |
|
264 |
|
|
265 |
ddebug = debug |
|
266 |
monitor.syncExec( new Runnable() { |
|
267 |
|
|
268 |
public void run() { |
|
269 |
println chartComposite |
|
270 |
def chart = chartEditor.getChart() |
|
271 |
|
|
272 |
/* |
|
273 |
println "chart: "+chart |
|
274 |
println "Plot: "+chart.getPlot() |
|
275 |
println "Dataset: "+chart.getPlot().getDataset() |
|
276 |
println "Renderer 1: "+chart.getPlot().getRenderer() |
|
277 |
*/ |
|
278 |
|
|
279 |
def renderer = new CAItemSelectionRenderer(ica, chart) { |
|
280 |
Area EMPTYAREA = new Area() |
|
281 |
|
|
282 |
@Override |
|
283 |
public void initItemLabelGenerator() { |
|
284 |
XYItemLabelGenerator generator = new XYItemLabelGenerator() { |
|
285 |
|
|
286 |
@Override |
|
287 |
public String generateLabel(XYDataset dataset, int series, int item) { |
|
288 |
if (series == 0 && rowHiddenStyle.contains(item)) { |
|
289 |
if (ddebug > 1) println "HIDDING ROW LABEL '$item' '${rows[item]}'" |
|
290 |
return "" |
|
291 |
} else if (series == 1 && colHiddenStyle.contains(item)) { |
|
292 |
if (ddebug > 1) println "HIDDING COL LABEL '$item' '${cols[item]}'" |
|
293 |
return "" |
|
294 |
} else if (series == 0 && rowLabelStyle.containsKey(item)) { |
|
295 |
if (ddebug > 1) println "RENAME ROW LABEL '$item' '${rows[item]}' -> '${rowLabelStyle[item]}'" |
|
296 |
return rowLabelStyle[item] |
|
297 |
} else if (series == 1 && colLabelStyle.containsKey(item)) { |
|
298 |
if (ddebug > 1) println "RENAME COL LABEL '$item' '${cols[item]}' -> '${colLabelStyle[item]}'" |
|
299 |
return colLabelStyle[item] |
|
300 |
} else { |
|
301 |
CAXYDataset caDataset = (CAXYDataset) dataset; |
|
302 |
return caDataset.getLabel(series, item); |
|
303 |
} |
|
304 |
} |
|
305 |
}; |
|
306 |
|
|
307 |
// don't use setBaseItemLabelGenerator BUT setDefaultItemLabelGenerator |
|
308 |
this.setDefaultItemLabelGenerator(generator); |
|
309 |
this.setDefaultItemLabelsVisible(true); |
|
310 |
} |
|
311 |
|
|
312 |
|
|
313 |
|
|
314 |
@Override |
|
315 |
public Font getItemLabelFont(int series, int item) { |
|
316 |
Font d = super.getItemLabelFont(series, item); |
|
317 |
Integer style = d.getStyle(); |
|
318 |
Integer size = d.getSize(); |
|
319 |
String family = d.getFontName(); |
|
320 |
|
|
321 |
// size |
|
322 |
if (series == 0 && rowFontSizeStyle.containsKey(item)) { |
|
323 |
if (ddebug > 1) println "FIX ROW FONT-SIZE $item ${rows[item]} -> ${rowFontSizeStyle[item]}" |
|
324 |
size *= rowFontSizeStyle[item]; |
|
325 |
} else if (series == 1 && colFontSizeStyle.containsKey(item)) { |
|
326 |
if (ddebug > 1) println "FIX COL FONT-SIZE $item ${cols[item]} -> ${colFontSizeStyle[item]}" |
|
327 |
size *= colFontSizeStyle[item]; |
|
328 |
} |
|
329 |
|
|
330 |
// family |
|
331 |
if (series == 0 && rowFontFamilyStyle.containsKey(item)) { |
|
332 |
if (ddebug > 1) println "FIX ROW FONT-Family $item ${rows[item]} -> ${rowFontFamilyStyle[item]}" |
|
333 |
family = rowFontFamilyStyle[item]; |
|
334 |
} else if (series == 1 && colFontFamilyStyle.containsKey(item)) { |
|
335 |
if (ddebug > 1) println "FIX COL FONT-Family $item ${cols[item]} -> ${colFontFamilyStyle[item]}" |
|
336 |
family = colFontFamilyStyle[item]; |
|
337 |
} |
|
338 |
|
|
339 |
// style |
|
340 |
if (series == 0 && rowFontStyleStyle.containsKey(item)) { |
|
341 |
if (ddebug > 1) println "FIX ROW FONT-Style $item ${rows[item]} -> ${rowFontStyleStyle[item]}" |
|
342 |
style = rowFontStyleStyle[item]; |
|
343 |
} else if (series == 1 && colFontFamilyStyle.containsKey(item)) { |
|
344 |
if (ddebug > 1) println "FIX COL FONT-Style $item ${cols[item]} -> ${colFontStyleStyle[item]}" |
|
345 |
style = colFontStyleStyle[item]; |
|
346 |
} |
|
347 |
|
|
348 |
|
|
349 |
return new Font(family, style, size); |
|
350 |
} |
|
351 |
|
|
352 |
|
|
353 |
@Override |
|
354 |
public Shape getItemShape(int series, int item) { |
|
355 |
// Rows (series == 0), Cols (series == 1) |
|
356 |
if (series == 0 && rowHiddenStyle.contains(item)) { |
|
357 |
return EMPTYAREA; |
|
358 |
} else if (series == 1 && colHiddenStyle.contains(item)) { |
|
359 |
return EMPTYAREA; |
|
360 |
} else { |
|
361 |
|
|
362 |
Shape shape = super.getItemShape(series, item); |
|
363 |
|
|
364 |
// not-visible shapes mode |
|
365 |
if(!((CA) this.multipleItemsSelector.getResult()).isShowPointShapes()) { |
|
366 |
return shape; |
|
367 |
} |
|
368 |
|
|
369 |
// shape replacement |
|
370 |
if (series == 0 && rowPointShapeStyle.containsKey(item)) { |
|
371 |
if (ddebug > 1) println "FIX ROW SHAPE $item ${rows[item]} -> ${rowPointShapeStyle[item]}" |
|
372 |
shape = rowPointShapeStyle.get(item); |
|
373 |
} else if (series == 1 && colPointShapeStyle.containsKey(item)) { |
|
374 |
if (ddebug > 1) println "FIX COL SHAPE $item ${cols[item]} -> ${colPointShapeStyle[item]}" |
|
375 |
shape = colPointShapeStyle.get(item); |
|
376 |
} |
|
377 |
|
|
378 |
|
|
379 |
// shape scaling |
|
380 |
AffineTransform t = new AffineTransform(); |
|
381 |
if (series == 0 && rowPointSizeStyle.containsKey(item)) { |
|
382 |
if (ddebug > 1) println "FIX ROW POINT SIZE $item ${rows[item]} -> ${rowPointSizeStyle[item]}" |
|
383 |
t.setToScale(rowPointSizeStyle.get(item), rowPointSizeStyle.get(item)); |
|
384 |
shape = t.createTransformedShape(shape); |
|
385 |
} else if (series == 1 && colPointSizeStyle.containsKey(item)) { |
|
386 |
if (ddebug > 1) println "FIX COL POINT SIZE $item ${cols[item]} -> ${colPointSizeStyle[item]}" |
|
387 |
t.setToScale(colPointSizeStyle.get(item), colPointSizeStyle.get(item)); |
|
388 |
shape = t.createTransformedShape(shape); |
|
389 |
} |
|
390 |
|
|
391 |
return shape; |
|
392 |
} |
|
393 |
} |
|
394 |
|
|
395 |
|
|
396 |
@Override |
|
397 |
public Paint getItemPaint(int series, int item) { |
|
398 |
|
|
399 |
// visible shapes mode |
|
400 |
if (!((CA) this.multipleItemsSelector.getResult()).isShowPointShapes()) { |
|
401 |
return super.getItemPaint(series, item); |
|
402 |
} |
|
403 |
|
|
404 |
if (series == 0 && rowPointColorStyle.containsKey(item)) { |
|
405 |
if (ddebug > 1) println "FIX ROW POINT COLOR $item ${rows[item]} -> ${rowPointColorStyle[item]}" |
|
406 |
return rowPointColorStyle.get(item); |
|
407 |
} else if (series == 1 && colPointColorStyle.containsKey(item)) { |
|
408 |
if (ddebug > 1) println "FIX COL POINT COLOR $item ${cols[item]} -> ${colPointColorStyle[item]}" |
|
409 |
return colPointColorStyle.get(item); |
|
410 |
} |
|
411 |
else { |
|
412 |
return super.getItemPaint(series, item); |
|
413 |
} |
|
414 |
} |
|
415 |
|
|
416 |
|
|
417 |
@Override |
|
418 |
public Paint getItemLabelPaint(int series, int item) { |
|
419 |
if (series == 0 && rowFontColorStyle.containsKey(item)) { |
|
420 |
if (ddebug > 1) println "FIX ROW LABEL COLOR $item ${rows[item]} -> ${rowFontColorStyle[item]}" |
|
421 |
return rowFontColorStyle.get(item); |
|
422 |
} else if (series == 1 && colFontColorStyle.containsKey(item)) { |
|
423 |
if (ddebug > 1) println "FIX COL LABEL COLOR $item ${cols[item]} -> ${colFontColorStyle[item]}" |
|
424 |
return colFontColorStyle.get(item); |
|
425 |
} else { |
|
426 |
return super.getItemLabelPaint(series, item); |
|
427 |
} |
|
428 |
} |
|
429 |
|
|
430 |
}; |
|
431 |
|
|
432 |
|
|
433 |
def cp = editor.editors[0].getChart(); |
|
434 |
renderer.chart = cp // SJ: seems useless |
|
435 |
renderer.setSeriesVisible(0, ica.isShowVariables()); // Rows // SJ: seems useless |
|
436 |
renderer.setSeriesVisible(1, ica.isShowIndividuals()); // Columns // SJ: seems useless |
|
437 |
chart.getXYPlot().setRenderer(renderer) |
|
438 |
|
|
439 |
ica.getChartCreator().updateChart(chartEditor.getResult()) |
|
440 |
|
|
441 |
} |
|
442 |
}); |
|
443 |
|
|
444 |
|
|
445 |
|
|
446 |
|
|
447 |
// creates a Color object from the specified RGB or RGBA string representation separated by spaces ("R G B" or "R G B A") from 0 to 255 for each channel |
|
448 |
def rgbaStringToColor(String color) { |
|
449 |
String[] rgbColor = color.split(" "); |
|
450 |
String alpha = "255"; |
|
451 |
if(rgbColor.length > 2) { |
|
452 |
if(rgbColor.length > 3) { |
|
453 |
alpha = rgbColor[3]; |
|
454 |
} |
|
455 |
return new Color(Integer.parseInt(rgbColor[0]), Integer.parseInt(rgbColor[1]), Integer.parseInt(rgbColor[2]), Integer.parseInt(alpha)) |
|
456 |
} |
|
457 |
else { |
|
458 |
println "Error in color format for RGB or RGBA string: $color" |
|
459 |
} |
|
460 |
} |
|
461 |
|
|
462 |
|
|
463 |
|
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/CAFilter.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
package org.txm.macro |
|
3 |
|
|
4 |
import org.kohsuke.args4j.* |
|
5 |
import groovy.transform.Field |
|
6 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
7 |
import org.txm.searchengine.cqp.clientExceptions.* |
|
8 |
import org.txm.searchengine.cqp.corpus.* |
|
9 |
import org.txm.searchengine.cqp.corpus.query.* |
|
10 |
import org.apache.commons.lang.time.StopWatch |
|
11 |
import java.util.Arrays |
|
12 |
import org.jfree.chart.renderer.xy.* |
|
13 |
import org.jfree.chart.renderer.* |
|
14 |
import org.jfree.chart.plot.* |
|
15 |
import org.jfree.data.xy.* |
|
16 |
import org.jfree.chart.axis.* |
|
17 |
import java.awt.*; |
|
18 |
import java.awt.geom.*; |
|
19 |
import org.jfree.chart.labels.* |
|
20 |
|
|
21 |
import org.txm.ca.core.chartsengine.jfreechart.themes.highcharts.renderers.* |
|
22 |
import org.txm.ca.rcp.editors.* |
|
23 |
import org.txm.libs.office.ReadODS |
|
24 |
import org.txm.ca.core.chartsengine.jfreechart.datasets.* |
|
25 |
import org.jfree.chart.renderer.AbstractRenderer |
|
26 |
|
|
27 |
import org.apache.commons.math3.stat.descriptive.* |
|
28 |
|
|
29 |
println "editor: "+editor |
|
30 |
|
|
31 |
if (!(editor instanceof CAEditor)) { |
|
32 |
println "editor is not a CA editor: $editor, Run the macro with F12 when the editor is selected :-)" |
|
33 |
return |
|
34 |
} |
|
35 |
|
|
36 |
def chartEditor = editor.getEditors()[0] |
|
37 |
def chartComposite = chartEditor.getComposite() |
|
38 |
|
|
39 |
// BEGINNING OF PARAMETERS |
|
40 |
|
|
41 |
// Declare each parameter here |
|
42 |
// (available widget types: Query, File, Folder, String, Text, Boolean, Integer, Float and Date) |
|
43 |
|
|
44 |
//@Field @Option(name="query", usage="an example query", widget="Query", required=true, def='[pos="V.*"]') |
|
45 |
//def query |
|
46 |
|
|
47 |
//@Field @Option(name="file", usage="an example file", widget="File", required=true, def="C:/Temp/foo.txt") |
|
48 |
//def file |
|
49 |
|
|
50 |
//@Field @Option(name="folder", usage="an example folder", widget="Folder", required=false, def="C:/Temp") |
|
51 |
//def folder |
|
52 |
|
|
53 |
//@Field @Option(name="date", usage="an example date", widget="Date", required=false, def="1984-09-01") |
|
54 |
//def date |
|
55 |
|
|
56 |
//@Field @Option(name="integer", usage="an example integer", widget="Integer", required=false, def="42") |
|
57 |
//def integer |
|
58 |
|
|
59 |
@Field @Option(name="QMin", usage="min Q", widget="Float", required=true, def="0.01") |
|
60 |
def QMin |
|
61 |
|
|
62 |
@Field @Option(name="CTRXMin", usage="min CTR X", widget="Float", required=true, def="0.001") |
|
63 |
def CTRXMin |
|
64 |
|
|
65 |
@Field @Option(name="CTRYMin", usage="min CTR Y", widget="Float", required=true, def="0.001") |
|
66 |
def CTRYMin |
|
67 |
|
|
68 |
@Field @Option(name="stackX", usage="stack X", widget="Float", required=true, def="0.0") |
|
69 |
def stackX |
|
70 |
|
|
71 |
@Field @Option(name="stackY", usage="stack Y", widget="Float", required=true, def="0.0") |
|
72 |
def stackY |
|
73 |
|
|
74 |
//@Field @Option(name="string", usage="an example string", widget="String", required=false, def="hello world!") |
|
75 |
//def string |
|
76 |
|
|
77 |
@Field @Option(name="regexFilter", usage="row property form regex", widget="Text", required=false, def="") |
|
78 |
def regexFilter |
|
79 |
|
|
80 |
@Field @Option(name="debug", usage="debug (verbose) mode", widget="Boolean", required=true, def="true") |
|
81 |
def debug |
|
82 |
|
|
83 |
// La fenêtre de résultats |
|
84 |
CAresultWindow = editor |
|
85 |
|
|
86 |
// Le tableau de données d'aide à l'interprétation |
|
87 |
// Les données de l'AFC sont manipulables par les méthodes documentées ici http://txm.sourceforge.net/javadoc/TXM/TBX/org/txm/stat/engine/r/function/CA.html |
|
88 |
|
|
89 |
ica = CAresultWindow.getCA() |
|
90 |
ca = ica.getCA() |
|
91 |
|
|
92 |
rowNames = ica.getRowNames() |
|
93 |
rowCos2 = ca.getRowCos2() |
|
94 |
rowContrib = ca.getRowContrib() |
|
95 |
|
|
96 |
colNames = ica.getColNames() |
|
97 |
colCos2 = ca.getColCos2() |
|
98 |
colContrib = ca.getColContrib() |
|
99 |
|
|
100 |
F1 = ica.getFirstDimension()-1 |
|
101 |
F2 = ica.getSecondDimension()-1 |
|
102 |
|
|
103 |
println sprintf("F1 = %d, F2 = %d, %d initial rows, %d initial cols", F1+1, F2+1, rowNames.length, colNames.length) |
|
104 |
|
|
105 |
def stats = { vector, factor -> |
|
106 |
s = new DescriptiveStatistics() |
|
107 |
(vector.length).times { |
|
108 |
s.addValue(vector[it][factor]); |
|
109 |
} |
|
110 |
|
|
111 |
println "min quartile median third quartile max" |
|
112 |
println sprintf("%8f %8f %8f %8f %8f", s.getMin(), s.getPercentile(25), s.getPercentile(50), s.getPercentile(75), s.getMax()) |
|
113 |
} |
|
114 |
|
|
115 |
// rows |
|
116 |
|
|
117 |
println "ROWS -----" |
|
118 |
println "CTR"+(F1+1) |
|
119 |
stats(rowContrib, F1) |
|
120 |
|
|
121 |
println "CTR"+(F2+1) |
|
122 |
stats(rowContrib, F2) |
|
123 |
|
|
124 |
println "Cos² "+(F1+1) |
|
125 |
stats(rowCos2, F1) |
|
126 |
|
|
127 |
println "Cos² "+(F2+1) |
|
128 |
stats(rowCos2, F2) |
|
129 |
|
|
130 |
// cols |
|
131 |
|
|
132 |
println "COLS -----" |
|
133 |
println "CTR"+(F1+1) |
|
134 |
stats(colContrib, F1) |
|
135 |
|
|
136 |
println "CTR"+(F2+1) |
|
137 |
stats(colContrib, F2) |
|
138 |
|
|
139 |
println "Cos² "+(F1+1) |
|
140 |
stats(colCos2, F1) |
|
141 |
|
|
142 |
println "Cos² "+(F2+1) |
|
143 |
stats(colCos2, F2) |
|
144 |
|
|
145 |
|
|
146 |
def stats2 = { vector, factor1, factor2 -> |
|
147 |
s = new DescriptiveStatistics() |
|
148 |
(vector.length).times { |
|
149 |
s.addValue(vector[it][factor1]+vector[it][factor2]); |
|
150 |
} |
|
151 |
|
|
152 |
println "min quartile median third quartile max" |
|
153 |
println sprintf("%8f %8f %8f %8f %8f", s.getMin(), s.getPercentile(25), s.getPercentile(50), s.getPercentile(75), s.getMax()) |
|
154 |
} |
|
155 |
|
|
156 |
println "Q"+(F1+1)+(F2+1) |
|
157 |
stats2(rowCos2, F1, F2) |
|
158 |
|
|
159 |
println "Q"+(F1+1)+(F2+1) |
|
160 |
stats2(colCos2, F1, F2) |
|
161 |
|
|
162 |
// Open the parameters input dialog box |
|
163 |
if (!ParametersDialog.open(this)) return |
|
164 |
|
|
165 |
// END OF PARAMETERS |
|
166 |
|
|
167 |
|
|
168 |
filteredRows = [] |
|
169 |
|
|
170 |
println "" |
|
171 |
|
|
172 |
if (debug) println "\nROWS -----" |
|
173 |
|
|
174 |
if (regexFilter.length() > 0) { |
|
175 |
nmatched = 0 |
|
176 |
rowNames.each { it -> |
|
177 |
if (it ==~ regexFilter) { |
|
178 |
if (debug && !filteredRows.contains(it)) { |
|
179 |
if (nmatched > 0) print ", " |
|
180 |
print it |
|
181 |
} |
|
182 |
filteredRows << it |
|
183 |
nmatched++ |
|
184 |
} |
|
185 |
} |
|
186 |
|
|
187 |
if (debug && nmatched > 0) println "" |
|
188 |
|
|
189 |
if (debug) { |
|
190 |
println sprintf("\n%d rows filtered by regex", nmatched) |
|
191 |
} |
|
192 |
|
|
193 |
} |
|
194 |
|
|
195 |
nQCTR = 0 |
|
196 |
rowNames.eachWithIndex { it, i -> |
|
197 |
def cos2 = rowCos2[i] |
|
198 |
if ((rowContrib[i][F1] < CTRXMin) && (rowContrib[i][F2] < CTRYMin) && (cos2[F1] + cos2[F2] < QMin)) { |
|
199 |
if (debug && !filteredRows.contains(rowNames[i])) { |
|
200 |
if (nQCTR > 0) print ", " |
|
201 |
print rowNames[i] |
|
202 |
} |
|
203 |
filteredRows << rowNames[i] |
|
204 |
nQCTR++ |
|
205 |
} |
|
206 |
} |
|
207 |
|
|
208 |
if (debug) { |
|
209 |
println sprintf("\n%d rows filtered by CTR or Q"+(F1+1)+(F2+1), nQCTR) |
|
210 |
} |
|
211 |
|
|
212 |
// cols |
|
213 |
|
|
214 |
filteredCols = [] |
|
215 |
|
|
216 |
println "" |
|
217 |
|
|
218 |
if (debug) println "\nCOLS -----" |
|
219 |
|
|
220 |
if (regexFilter.length() > 0) { |
|
221 |
nmatched = 0 |
|
222 |
colNames.each { it -> |
|
223 |
if (it ==~ regexFilter) { |
|
224 |
if (debug && !filteredCols.contains(it)) { |
|
225 |
if (nmatched > 0) print ", " |
|
226 |
print it |
|
227 |
} |
|
228 |
filteredCols << it |
|
229 |
nmatched++ |
|
230 |
} |
|
231 |
} |
|
232 |
|
|
233 |
if (debug && nmatched > 0) println "" |
|
234 |
|
|
235 |
if (debug) { |
|
236 |
println sprintf("\n%d cols filtered by regex", nmatched) |
|
237 |
} |
|
238 |
|
|
239 |
} |
|
240 |
|
|
241 |
nQCTR = 0 |
|
242 |
colNames.eachWithIndex { it, i -> |
|
243 |
def cos2 = colCos2[i] |
|
244 |
if (!((colContrib[i][F1] > CTRXMin) || (colContrib[i][F2] > CTRYMin) || (cos2[F1] + cos2[F2] > QMin))) { |
|
245 |
if (debug && !filteredCols.contains(colNames[i])) { |
|
246 |
if (nQCTR > 0) print ", " |
|
247 |
print colNames[i] |
|
248 |
} |
|
249 |
filteredCols << colNames[i] |
|
250 |
nQCTR++ |
|
251 |
} |
|
252 |
} |
|
253 |
|
|
254 |
if (debug) { |
|
255 |
println sprintf("\n%d cols filtered by CTR or Q"+(F1+1)+(F2+1), nQCTR) |
|
256 |
} |
|
257 |
|
|
258 |
double stackXv = stackX |
|
259 |
double stackYv = stackY |
|
260 |
|
|
261 |
|
|
262 |
// Visualisation graphique |
|
263 |
|
|
264 |
chartCAresultWindow = CAresultWindow.getEditors()[0] |
|
265 |
chartComposite = chartCAresultWindow.getComposite() |
|
266 |
|
|
267 |
monitor.syncExec( new Runnable() { |
|
268 |
public void run() { |
|
269 |
|
|
270 |
println chartComposite |
|
271 |
def chart = chartEditor.getChart(); |
|
272 |
|
|
273 |
dataset2 = new CAXYDataset(ica) |
|
274 |
|
|
275 |
labels = dataset2.rowLabels |
|
276 |
coords = dataset2.rowCoordinates |
|
277 |
(labels.length).times { |
|
278 |
if (filteredRows.contains(labels[it])) { |
|
279 |
println "Moving "+labels[it]+" row to origin." |
|
280 |
labels[it] = "" |
|
281 |
coords[it][F1] = stackXv |
|
282 |
coords[it][F2] = stackYv |
|
283 |
} |
|
284 |
} |
|
285 |
labels = dataset2.columnLabels |
|
286 |
coords = dataset2.columnCoordinates |
|
287 |
(labels.length).times { |
|
288 |
if (filteredCols.contains(labels[it])) { |
|
289 |
println "Moving "+labels[it]+" col to origin." |
|
290 |
labels[it] = "" |
|
291 |
coords[it][F1] = stackXv |
|
292 |
coords[it][F2] = stackYv |
|
293 |
} |
|
294 |
} |
|
295 |
|
|
296 |
chart.getXYPlot().setDataset(dataset2) |
|
297 |
|
|
298 |
ica.getChartCreator().getChartsEngine().getJFCTheme().apply(chart); // need to be call AFTER setRenderer() cause this method changes some renderering parameters |
|
299 |
chartComposite.loadChart() |
|
300 |
} |
|
301 |
}) |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/InvertCAXAxisMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// @author Sebastien Jacquot |
|
2 |
// STANDARD DECLARATIONS |
|
3 |
package org.txm.macro |
|
4 |
|
|
5 |
|
|
6 |
import org.kohsuke.args4j.* |
|
7 |
import groovy.transform.Field |
|
8 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
9 |
import org.txm.searchengine.cqp.clientExceptions.* |
|
10 |
import org.txm.searchengine.cqp.corpus.* |
|
11 |
import org.txm.searchengine.cqp.corpus.query.* |
|
12 |
import org.apache.commons.lang.time.StopWatch |
|
13 |
import java.util.Arrays |
|
14 |
import org.jfree.chart.renderer.xy.* |
|
15 |
import org.jfree.chart.renderer.* |
|
16 |
import org.jfree.chart.plot.* |
|
17 |
import org.jfree.data.xy.* |
|
18 |
import org.jfree.chart.axis.* |
|
19 |
import java.awt.*; |
|
20 |
import java.awt.geom.*; |
|
21 |
import org.jfree.chart.labels.* |
|
22 |
|
|
23 |
import org.txm.ca.core.chartsengine.jfreechart.themes.highcharts.renderers.* |
|
24 |
import org.txm.ca.rcp.editors.* |
|
25 |
import org.txm.libs.office.ReadODS |
|
26 |
import org.txm.ca.core.chartsengine.jfreechart.datasets.* |
|
27 |
import org.jfree.chart.renderer.AbstractRenderer |
|
28 |
|
|
29 |
println "editor: "+editor |
|
30 |
|
|
31 |
if (!(editor instanceof CAEditor)) { |
|
32 |
println "editor is not a CA editor: $editor, Run the macro with F12 when the editor is selected :-)" |
|
33 |
return |
|
34 |
} |
|
35 |
|
|
36 |
ica = editor.getCA(); |
|
37 |
chart = ica.getChart(); |
|
38 |
plot = chart.getXYPlot(); |
|
39 |
dataset = plot.getDataset(); |
|
40 |
|
|
41 |
// overrides some dataset methods to return inverted X coordinates for columns and rows |
|
42 |
plot.setDataset(new CAXYDataset(ica) { |
|
43 |
|
|
44 |
public Number getX(int series, int item) { |
|
45 |
if(item == -1) { |
|
46 |
System.out.println("CAXYDataset.getX()"); |
|
47 |
} |
|
48 |
// Rows |
|
49 |
if(series == 0) { |
|
50 |
return -this.rowCoordinates[item][this.axis1]; |
|
51 |
} |
|
52 |
// Cols |
|
53 |
else { |
|
54 |
return -this.columnCoordinates[item][this.axis1]; |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
58 |
|
|
59 |
|
|
60 |
/** |
|
61 |
* Gets the minimum value in the specified series according to the specified axis. |
|
62 |
* @param series |
|
63 |
* @param axis |
|
64 |
* @return |
|
65 |
*/ |
|
66 |
public double getMinValue(int series, int axis) { |
|
67 |
double minValue = 0; |
|
68 |
double tmpMinValue; |
|
69 |
double[][] coordinates = this.rowCoordinates; |
|
70 |
if(series != 0) { |
|
71 |
coordinates = this.columnCoordinates; |
|
72 |
} |
|
73 |
|
|
74 |
for(int i = 0; i < coordinates.length; i++) { |
|
75 |
tmpMinValue = coordinates[i][axis]; |
|
76 |
|
|
77 |
// invert X coordinate |
|
78 |
if(axis == 0) { |
|
79 |
tmpMinValue = -tmpMinValue; |
|
80 |
} |
|
81 |
|
|
82 |
if(tmpMinValue < minValue) { |
|
83 |
minValue = tmpMinValue; |
|
84 |
} |
|
85 |
} |
|
86 |
|
|
87 |
return minValue; |
|
88 |
} |
|
89 |
|
|
90 |
/** |
|
91 |
* Gets the maximum value in the specified series according to the specified axis. |
|
92 |
* @param series |
|
93 |
* @param axis |
|
94 |
* @return |
|
95 |
*/ |
|
96 |
public double getMaxValue(int series, int axis) { |
|
97 |
double maxValue = 0; |
|
98 |
double tmpMaxValue; |
|
99 |
double[][] coordinates = this.rowCoordinates; |
|
100 |
if(series != 0) { |
|
101 |
coordinates = this.columnCoordinates; |
|
102 |
} |
|
103 |
|
|
104 |
for(int i = 0; i < coordinates.length; i++) { |
|
105 |
tmpMaxValue = coordinates[i][axis]; |
|
106 |
|
|
107 |
// invert X coordinate |
|
108 |
if(axis == 0) { |
|
109 |
tmpMaxValue = -tmpMaxValue; |
|
110 |
} |
|
111 |
|
|
112 |
if(tmpMaxValue > maxValue) { |
|
113 |
maxValue = tmpMaxValue; |
|
114 |
} |
|
115 |
} |
|
116 |
|
|
117 |
return maxValue; |
|
118 |
} |
|
119 |
} |
|
120 |
); |
|
121 |
|
|
122 |
// update the limits dotted borders |
|
123 |
ica.getChartCreator().createCAFactorialMapChartLimitsBorder(chart); |
|
124 |
|
|
125 |
|
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/PlotEllipsesMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
package org.txm.macro |
|
3 |
|
|
4 |
import org.txm.ca.core.functions.CA |
|
5 |
import org.txm.statsengine.r.core.RWorkspace |
|
6 |
import groovy.transform.Field |
|
7 |
// BEGINNING OF PARAMETERS |
|
8 |
|
|
9 |
if (!(corpusViewSelection instanceof CA)) { |
|
10 |
println "Selection is not a CA. Please select a CA result in the Corpus view" |
|
11 |
return; |
|
12 |
} |
|
13 |
|
|
14 |
def ca = corpusViewSelection |
|
15 |
|
|
16 |
@Field @Option(name="outputFile", usage="an example file", widget="FileSave", required=true, def="file.svg") |
|
17 |
def outputFile |
|
18 |
|
|
19 |
@Field @Option(name="draw", usage="'row' or 'col'", widget="String", required=true, def="row") |
|
20 |
def draw |
|
21 |
// Open the parameters input dialog box |
|
22 |
if (!ParametersDialog.open(this)) return; |
|
23 |
|
|
24 |
// END OF PARAMETERS |
|
25 |
|
|
26 |
def s = ca.getRSymbol() |
|
27 |
def RW = RWorkspace.getRWorkspaceInstance() |
|
28 |
|
|
29 |
def script = """ |
|
30 |
plot($s); |
|
31 |
ellipseCA($s, ellipse=c("$draw")); |
|
32 |
""" |
|
33 |
|
|
34 |
RW.plot(outputFile, script); |
|
35 |
|
|
36 |
println "Done: "+outputFile.getAbsolutePath() |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/.~lock.clearPattern.ods# (revision 3555) | ||
---|---|---|
1 |
,mdecorde,L107533,14.10.2022 11:02,file:///home/mdecorde/.config/libreoffice/4; |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/prototypes/stats/.~lock.resultPattern.ods# (revision 3555) | ||
---|---|---|
1 |
,mdecorde,L107533,14.10.2022 11:05,file:///home/mdecorde/.config/libreoffice/4; |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/stats/PlotEllipsesMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
package org.txm.macro.stats |
|
3 |
|
|
4 |
import org.txm.ca.core.functions.CA |
|
5 |
import org.txm.statsengine.r.core.RWorkspace |
|
6 |
import groovy.transform.Field |
|
7 |
// BEGINNING OF PARAMETERS |
|
8 |
|
|
9 |
if (!(corpusViewSelection instanceof CA)) { |
|
10 |
println "Selection is not a CA. Please select a CA result in the Corpus view" |
|
11 |
return; |
|
12 |
} |
|
13 |
|
|
14 |
def ca = corpusViewSelection |
|
15 |
|
|
16 |
@Field @Option(name="outputFile", usage="an example file", widget="FileSave", required=true, def="file.svg") |
|
17 |
def outputFile |
|
18 |
|
|
19 |
@Field @Option(name="draw", usage="'row' or 'col'", widget="String", required=true, def="row") |
|
20 |
def draw |
|
21 |
// Open the parameters input dialog box |
|
22 |
if (!ParametersDialog.open(this)) return; |
|
23 |
|
|
24 |
// END OF PARAMETERS |
|
25 |
|
|
26 |
def s = ca.getRSymbol() |
|
27 |
def RW = RWorkspace.getRWorkspaceInstance() |
|
28 |
|
|
29 |
def script = """ |
|
30 |
plot($s); |
|
31 |
ellipseCA($s, ellipse=c("$draw")); |
|
32 |
""" |
|
33 |
|
|
34 |
RW.plot(outputFile, script); |
|
35 |
|
|
36 |
println "Done: "+outputFile.getAbsolutePath() |
TXM/trunk/org.txm.groovy.core/src/groovy/org/txm/macro/stats/CAStyleMacro.groovy (revision 3555) | ||
---|---|---|
1 |
// STANDARD DECLARATIONS |
|
2 |
// @author mdecorde sjacquot sheiden |
|
3 |
package org.txm.macro.stats |
|
4 |
|
|
5 |
import org.kohsuke.args4j.* |
|
6 |
import groovy.transform.Field |
|
7 |
import org.txm.rcpapplication.swt.widget.parameters.* |
|
8 |
import org.txm.searchengine.cqp.clientExceptions.* |
|
9 |
import org.txm.searchengine.cqp.corpus.* |
|
10 |
import org.txm.searchengine.cqp.corpus.query.* |
|
11 |
import org.apache.commons.lang.time.StopWatch |
|
12 |
import java.util.Arrays |
|
13 |
import org.jfree.chart.renderer.xy.* |
|
14 |
import org.jfree.chart.renderer.* |
|
15 |
import org.jfree.chart.plot.* |
|
16 |
import org.jfree.data.xy.* |
|
17 |
import org.jfree.chart.axis.* |
|
18 |
import java.awt.*; |
|
19 |
import java.awt.geom.*; |
|
20 |
import org.jfree.chart.labels.* |
|
21 |
|
|
22 |
import org.txm.ca.core.functions.CA |
|
23 |
import org.txm.ca.core.chartsengine.jfreechart.themes.highcharts.renderers.* |
|
24 |
import org.txm.ca.rcp.editors.* |
|
25 |
import org.txm.libs.office.ReadODS |
|
26 |
import org.txm.ca.core.chartsengine.jfreechart.datasets.* |
|
27 |
import org.jfree.chart.renderer.AbstractRenderer |
|
28 |
import java.awt.geom.Ellipse2D |
|
29 |
import org.jfree.chart.util.ShapeUtils |
|
30 |
|
|
31 |
|
|
32 |
println "editor: "+editor |
|
33 |
|
|
34 |
if (!(editor instanceof CAEditor)) { |
|
35 |
println "editor is not a CA editor: $editor, Run the macro with F12 when the editor is selected :-)" |
|
36 |
return |
|
37 |
} |
|
38 |
|
|
39 |
@Field @Option(name="patternsODSFile", usage="The starting word", widget="FileOpen", required=true, def='patterns.ods') |
|
40 |
def patternsODSFile |
|
41 |
@Field @Option(name="debug", usage="Show internal variable content", widget="StringArray", metaVar="OFF ON ALL REALLY ALL", required=true, def="OFF") |
|
42 |
debug |
|
43 |
|
|
44 |
// Open the parameters input dialog box |
|
45 |
if (!ParametersDialog.open(this)) return; |
|
46 |
if (debug == "OFF") debug = 0; else if (debug == "ON") debug = 1; else if (debug == "ALL") debug = 2 else if (debug == "REALLY ALL") debug = 3 |
|
47 |
|
|
48 |
if (!patternsODSFile.exists()) { |
|
49 |
println "Pattern file not found: $patternsODSFile" |
|
50 |
return false; |
|
51 |
} |
|
52 |
if (!patternsODSFile.isFile() || !patternsODSFile.getName().toLowerCase().endsWith(".ods")) { |
|
53 |
println "Wrong pattern file: $patternsODSFile" |
|
54 |
return false; |
|
55 |
} |
|
56 |
|
|
57 |
def data = ReadODS.toTable(patternsODSFile, "rows") // read from the "rows" sheet |
|
58 |
def keys = data[0] |
|
59 |
def row_styles = [:] // reformat data |
|
60 |
for (int i = 1 ; i < data.size() ; i++) { |
|
61 |
def h = data[i] |
|
62 |
def style = [:] // create style entry |
|
63 |
String s = h[0]; |
|
64 |
row_styles[/$s/] = style // with a regexp pattern as key |
|
65 |
|
|
66 |
// fill the style |
|
67 |
for (int j = 1 ; j < h.size() ; j++) { |
|
68 |
style[keys[j]] = h[j] |
|
69 |
} |
|
70 |
} |
|
71 |
if (debug > 0) { |
|
72 |
println "ROW STYLES=$row_styles" |
|
73 |
} |
|
74 |
|
|
75 |
data = ReadODS.toTable(patternsODSFile, "cols") // read from the "cols" sheet |
|
76 |
keys = data[0] |
|
77 |
def col_styles = [:] // reformat data |
|
78 |
|
|
79 |
for (int i = 1 ; i < data.size() ; i++) { |
|
80 |
def h = data[i] |
|
81 |
def style = [:] // create style entry |
|
82 |
String s = h[0]; |
|
83 |
col_styles[/$s/] = style // with a regexp pattern as key |
|
84 |
|
|
85 |
// fill the style |
|
86 |
for (int j = 1 ; j < h.size() ; j++) { |
|
87 |
style[keys[j]] = h[j] |
|
88 |
} |
|
89 |
} |
|
90 |
if (debug > 0) { |
|
91 |
println "COL STYLES=$col_styles" |
|
92 |
} |
|
93 |
|
|
94 |
ica = editor.getCA() |
|
95 |
ca = ica.getCA() |
|
96 |
|
|
97 |
// http://txm.sourceforge.net/javadoc/TXM/TBX/org/txm/stat/engine/r/function/CA.html |
|
98 |
|
|
99 |
// SOME DATA |
|
100 |
rows = ica.getRowNames() |
|
101 |
rowsinfo = ica.getRowInfos() |
|
102 |
rowscos2 = ca.getRowCos2() |
|
103 |
cols = ica.getColNames() |
|
104 |
colssinfo = ica.getColInfos() |
|
105 |
colscos2 = ca.getColCos2() |
|
106 |
D1 = ica.getFirstDimension() -1; |
|
107 |
D2 = ica.getSecondDimension() -1; |
|
108 |
|
|
109 |
// create some AWT shapes for replacement |
|
110 |
shapes = new HashMap<String, Shape>(); |
|
111 |
// dimensions scaling factor (the same used in default theme for the replaced shapes have same dimension than non-replaced) |
|
112 |
float itemShapesScalingFactor = 1.2f |
|
113 |
shapes["diamond"] = ShapeUtils.createDiamond((float)(itemShapesScalingFactor * 3.4f)); |
|
114 |
shapes["square"] = AbstractRenderer.DEFAULT_SHAPE; |
|
115 |
|
|
116 |
float circleSize = 6.4f * itemShapesScalingFactor; |
|
117 |
shapes["disk"] = new Ellipse2D.Float((float)(-circleSize / 2), (float)(-circleSize / 2), circleSize, circleSize); |
|
118 |
|
|
119 |
shapes["triangle"] = ShapeUtils.createUpTriangle((float)(itemShapesScalingFactor * 3.2f)); |
|
120 |
|
|
121 |
//shapes["star"] = AbstractRenderer.DEFAULT_SHAPE; |
|
122 |
//shapes["circle"] = AbstractRenderer.DEFAULT_SHAPE; |
|
123 |
|
|
124 |
|
|
125 |
println "SHAPES=$shapes" |
|
126 |
|
|
127 |
|
|
128 |
// styles per col index in dataset |
|
129 |
// set col label |
|
130 |
colLabelStyle = new HashMap<Integer, String>(); |
|
131 |
// set col visibility |
|
132 |
colHiddenStyle = new HashSet<Integer>(); // true false |
|
133 |
// set col font size |
|
134 |
colFontSizeStyle = new HashMap<Integer, Float>(); |
|
135 |
// set col font color |
|
136 |
colFontColorStyle = new HashMap<Integer, Color>(); |
|
137 |
// set col font family |
|
138 |
colFontFamilyStyle = new HashMap<Integer, String>(); |
|
139 |
// set col points size |
|
140 |
colPointSizeStyle = new HashMap<Integer, Double>(); |
|
141 |
// set col points RGBA color |
|
142 |
colPointColorStyle = new HashMap<Integer, Color>(); |
|
143 |
// set col points shape (circle, square, triangle, ... + color ? + size ?) -> expert |
|
144 |
colPointShapeStyle = new HashMap<Integer, Shape>(); // circle, square, triangle, etc. |
|
145 |
// set col font style (1 = bold, 2 = italic, 3 = bold + italic) |
|
146 |
colFontStyleStyle = new HashMap<Integer, Integer>(); |
|
147 |
|
|
148 |
|
|
149 |
// set row label |
|
150 |
rowLabelStyle = new HashMap<Integer, String>(); |
|
151 |
// set row visibility |
|
152 |
rowHiddenStyle = new HashSet<Integer>(); // true false |
|
153 |
// set row font size |
|
154 |
rowFontSizeStyle = new HashMap<Integer, Float>(); |
|
155 |
// set row font size |
|
156 |
rowFontColorStyle = new HashMap<Integer, Color>(); |
|
157 |
// set row font size |
|
158 |
rowFontFamilyStyle = new HashMap<Integer, String>(); |
|
159 |
// set row points size |
|
160 |
rowPointSizeStyle = new HashMap<Integer, Double>(); |
|
161 |
// set row points RGBA color |
|
162 |
rowPointColorStyle = new HashMap<Integer, Color>(); |
|
163 |
// set row points shape (circle, square, triangle, ... + color ? + size ?) -> expert |
|
164 |
rowPointShapeStyle = new HashMap<Integer, Shape>(); // circle, square, triangle, etc. |
|
165 |
// set row font style (1 = bold, 2 = italic, 3 = bold + italic) |
|
166 |
rowFontStyleStyle = new HashMap<Integer, Integer>(); |
|
167 |
|
|
168 |
// prepare col style data for the dataset |
|
169 |
for (int i = 0 ; i < cols.length ; i++) { |
|
170 |
for (def p : col_styles.keySet()) { |
|
171 |
if (cols[i] ==~ p) { |
|
172 |
def style = col_styles[p] |
|
173 |
if (style["label-replacement"] != null && style["label-replacement"].length() > 0) { |
|
174 |
colLabelStyle[i] = style["label-replacement"] |
|
175 |
} |
|
176 |
if (style["hidden"] != null && style["hidden"].toUpperCase() == "T") { |
|
177 |
colHiddenStyle << i |
|
178 |
} |
|
179 |
if (style["shape-size"] != null && style["shape-size"].length() > 0) { |
|
180 |
colPointSizeStyle[i] = Double.parseDouble(style["shape-size"]) |
|
181 |
} |
|
182 |
if (style["shape-color"] != null && style["shape-color"].length() > 0 ) { |
|
183 |
colPointColorStyle[i] = rgbaStringToColor(style["shape-color"]) |
|
184 |
} |
|
185 |
if (style["shape-replacement"] != null && shapes.containsKey(style["shape-replacement"])) { |
|
186 |
colPointShapeStyle[i] = shapes[style["shape-replacement"]] |
|
187 |
} |
|
188 |
if (style["label-size"] != null && style["label-size"].length() > 0) { |
|
189 |
colFontSizeStyle[i] = Float.parseFloat(style["label-size"]) |
|
190 |
} |
|
191 |
if (style["label-color"] != null && style["label-color"].length() > 0) { |
|
192 |
colFontColorStyle[i] = rgbaStringToColor(style["label-color"]) |
|
193 |
} |
|
194 |
if (style["label-font-family"] != null && style["label-font-family"].length() > 0) { |
|
195 |
colFontFamilyStyle[i] = style["label-font-family"] |
|
196 |
} |
|
197 |
if (style["label-style"] != null && style["label-style"].length() > 0) { |
|
198 |
colFontStyleStyle[i] = Integer.parseInt(style["label-style"]) |
|
199 |
} |
|
200 |
|
|
201 |
} |
|
202 |
} |
|
203 |
} |
|
204 |
if (debug > 0) { |
|
205 |
println "COL COL=$colPointColorStyle" |
|
206 |
println "COL SHP=$colPointShapeStyle" |
|
207 |
println "COL LAB=$colLabelStyle" |
|
208 |
println "COL FONT-SIZ=$colFontSizeStyle" |
|
209 |
println "COL SIZ=$colPointSizeStyle" |
|
210 |
println "COL VIZ=$colHiddenStyle" |
|
211 |
println "COL STYLE=$colFontStyleStyle" |
|
212 |
} |
|
213 |
|
|
214 |
// prepare row style data for the dataset |
|
215 |
for (int i = 0 ; i < rows.length ; i++) { |
|
216 |
for (def p : row_styles.keySet()) { |
|
217 |
if (rows[i] ==~ p) { |
|
218 |
def style = row_styles[p] |
|
219 |
if (style["hidden"] != null && style["hidden"].toUpperCase() == "T") { |
|
220 |
rowHiddenStyle << i |
|
221 |
} |
|
222 |
if (style["label-replacement"] != null && style["label-replacement"].length() > 0) { |
|
223 |
rowLabelStyle[i] = style["label-replacement"] |
|
224 |
} |
|
225 |
if (style["shape-size"] != null && style["shape-size"].length() > 0) { |
|
226 |
rowPointSizeStyle[i] = Double.parseDouble(style["shape-size"]) |
|
227 |
} |
|
228 |
if (style["shape-color"] != null && style["shape-color"].length() > 0 ) { |
|
229 |
rowPointColorStyle[i] = rgbaStringToColor(style["shape-color"]) |
|
230 |
} |
|
231 |
if (style["shape-replacement"] != null && shapes.containsKey(style["shape-replacement"])) { |
|
232 |
rowPointShapeStyle[i] = shapes[style["shape-replacement"]] |
|
233 |
} |
|
234 |
if (style["label-size"] != null && style["label-size"].length() > 0) { |
Formats disponibles : Unified diff