1 | package de.uka.ipd.sdq.sensorframework.visualisation.rvisualisation.reportitems; |
2 | |
3 | import java.io.File; |
4 | import java.io.IOException; |
5 | import java.util.Arrays; |
6 | import java.util.Hashtable; |
7 | import java.util.Map; |
8 | |
9 | import org.eclipse.core.runtime.IStatus; |
10 | |
11 | import de.uka.ipd.sdq.sensorframework.visualisation.rvisualisation.RVisualisationPlugin; |
12 | import de.uka.ipd.sdq.sensorframework.visualisation.rvisualisation.utils.RConnection; |
13 | |
14 | /**Report item to display generated graphics. |
15 | * @author groenda |
16 | */ |
17 | public abstract class AbstractPlotReportItem extends AbstractRReportItem { |
18 | /** Default position of the legend. */ |
19 | public static final LegendPosition DEFAULT_LEGEND_POSITION = |
20 | LegendPosition.none; |
21 | /** Default size of the graphic. */ |
22 | public static final int DEFAULT_GRAPHIC_SIZE = 500; |
23 | /** Default font size for the graphic. */ |
24 | public static final int DEFAULT_FONT_SIZE = 12; |
25 | |
26 | /** Table of the R commands for ids. */ |
27 | private Map<String, String> dataCommandTable = new Hashtable<String, String>(); |
28 | /** Table of the displayed names. */ |
29 | private Map<String, String> nameTable = new Hashtable<String, String>(); |
30 | |
31 | /** The temporary graphic file. */ |
32 | private File temporaryRasterGraphicFile = null; |
33 | /** The temporary graphic file. */ |
34 | private File temporaryVectorGraphicFile = null; |
35 | /** Position of the legend relative to the graphic. */ |
36 | private LegendPosition legendPosition = DEFAULT_LEGEND_POSITION; |
37 | /** The colors to use in the graphic. */ |
38 | private String[] colors = new String[] { "black", "lightgray", "darkgray", "gray" }; |
39 | /** Default height of the graphic. */ |
40 | private int graphicsHeight = DEFAULT_GRAPHIC_SIZE; |
41 | /** Default width of the graphic. */ |
42 | private int graphicsWidth = DEFAULT_GRAPHIC_SIZE; |
43 | /** Default font size for graphics. */ |
44 | private int fontSize = DEFAULT_FONT_SIZE; |
45 | |
46 | /**Position of the legend relative to the plot. |
47 | * @author happe |
48 | * @author groenda |
49 | */ |
50 | public enum LegendPosition { |
51 | /**The different legend positions. */ |
52 | none, top, topright, right, bottomright, bottom, bottomleft, left, |
53 | /**The different legend positions. */ |
54 | topleft, center |
55 | } |
56 | |
57 | /**Constructs a new report item containing a plotted density graphic. |
58 | * The graphic is stored in a temporary file. This is accessible via the |
59 | * getFilename method. |
60 | * @param title Title of the plotted graphic. |
61 | */ |
62 | public AbstractPlotReportItem(final String title) { |
63 | super(title); |
64 | } |
65 | |
66 | /**Constructs a new report item containing a plotted density graphic. |
67 | * The graphic is stored in a temporary file. This is accessible via the |
68 | * getFilename method. |
69 | * @param title Title of the plotted graphic. |
70 | * @param height height of the plotted graphic. |
71 | * @param width width of the plotted graphics. |
72 | * @param fontSize the default pointsize of plotted text, interpreted at |
73 | * 72 dpi, so one point is approximately one pixel. |
74 | */ |
75 | public AbstractPlotReportItem(final String title, final int height, |
76 | final int width, final int fontSize) { |
77 | super(title); |
78 | this.graphicsWidth = width; |
79 | this.graphicsHeight = height; |
80 | this.fontSize = fontSize; |
81 | } |
82 | |
83 | /**Adds a new data set to the plot. |
84 | * @param id Identifier for the data series. |
85 | * @param displayName The display name for the data series. |
86 | * @param rVariable The name of the R variable. |
87 | */ |
88 | public void addData(final String id, final String displayName, |
89 | final String rVariable) { |
90 | dataCommandTable.put(id, rVariable); |
91 | nameTable.put(id, displayName); |
92 | } |
93 | |
94 | /**Remove the data series from the plot. |
95 | * @param id Identifier of the data series. |
96 | */ |
97 | public void removeData(final String id) { |
98 | dataCommandTable.remove(id); |
99 | nameTable.remove(id); |
100 | } |
101 | |
102 | /**Returns the identifiers for the data series. |
103 | * @return the identifiers. |
104 | */ |
105 | protected String[] getDataSeries() { |
106 | String[] identifiers = new String[dataCommandTable.keySet().size()]; |
107 | dataCommandTable.keySet().toArray(identifiers); |
108 | Arrays.sort(identifiers); |
109 | return identifiers; |
110 | } |
111 | |
112 | /**Get the name for the data series. |
113 | * @param id The identifier of the data series. |
114 | * @return The name of the data series. |
115 | */ |
116 | protected String getName(final String id) { |
117 | return nameTable.get(id); |
118 | } |
119 | |
120 | /**Get the R variable for the data series. |
121 | * @param id The identifier of the data series. |
122 | * @return The name of the data series. |
123 | */ |
124 | protected String getDataCommand(final String id) { |
125 | return dataCommandTable.get(id); |
126 | } |
127 | |
128 | /** {@inheritDoc} |
129 | */ |
130 | @Override |
131 | public void visit(final IReportRenderingVisitor v) { |
132 | v.visitGraphicReportItem(this); |
133 | } |
134 | |
135 | /**Returns the complete path to the temporary file containing the |
136 | * raster graphic. |
137 | * @return The complete path. |
138 | */ |
139 | public String getTemporaryRasterGraphicFilename() { |
140 | if (dataCommandTable.size() == 0) { |
141 | return null; |
142 | } else { |
143 | return temporaryRasterGraphicFile.getAbsolutePath(); |
144 | } |
145 | } |
146 | |
147 | /**Returns the complete path to the temporary file containing the |
148 | * vector graphic. |
149 | * @return The complete path. |
150 | */ |
151 | public String getTemporaryVectorGraphicFilename() { |
152 | if (dataCommandTable.size() == 0) { |
153 | return null; |
154 | } else { |
155 | return temporaryVectorGraphicFile.getAbsolutePath(); |
156 | } |
157 | } |
158 | |
159 | /**Overwrite this method to generate custom graphics. |
160 | * @return The R command which execution leads to the creation of the plot. |
161 | */ |
162 | protected abstract String generatePlotCommand(); |
163 | |
164 | /**Exports the plot as vector graphic in the PDF format. |
165 | * @param pdfFile The file to which the graphic is saved. |
166 | * @param rConnection The connection to the R engine. |
167 | */ |
168 | public void generateVectorGraphic(final File pdfFile, |
169 | final RConnection rConnection) { |
170 | String rCommand = ""; |
171 | try { |
172 | rCommand += "pdf(\"" |
173 | + pdfFile.getAbsolutePath().replace("\\", |
174 | "\\\\") + "\")\n"; |
175 | rCommand += generatePlotCommand(); |
176 | rCommand += "dev.off()\n"; |
177 | } catch (Exception e) { |
178 | RVisualisationPlugin.log(IStatus.ERROR, |
179 | "Could not create PDF file. " |
180 | + e.getClass().getCanonicalName()); |
181 | } |
182 | rConnection.execute(rCommand); |
183 | } |
184 | |
185 | /**Exports the plot as raster graphic in the PNG format. |
186 | * @param pngFile The file to which the graphic is saved. |
187 | * @param rConnection The connection to the R engine. |
188 | */ |
189 | public void generateRasterGraphic(final File pngFile, |
190 | final RConnection rConnection) { |
191 | String rCommand = ""; |
192 | try { |
193 | rCommand += "png(\"" |
194 | + pngFile.getAbsolutePath().replace("\\", |
195 | "\\\\") + "\",height=" + graphicsHeight + ",width=" |
196 | + graphicsWidth + ",pointsize=" + fontSize + ")\n"; |
197 | rCommand += generatePlotCommand(); |
198 | rCommand += "dev.off()\n"; |
199 | } catch (Exception e) { |
200 | RVisualisationPlugin.log(IStatus.ERROR, |
201 | "Could not create temporary graphic file. " |
202 | + e.getClass().getCanonicalName()); |
203 | } |
204 | rConnection.execute(rCommand); |
205 | } |
206 | |
207 | /** {@inheritDoc} |
208 | */ |
209 | public void generateData(final RConnection connection) { |
210 | // generate raster image |
211 | try { |
212 | temporaryRasterGraphicFile = |
213 | File.createTempFile("pcm_pic", ".png"); |
214 | temporaryRasterGraphicFile.deleteOnExit(); |
215 | generateRasterGraphic(temporaryRasterGraphicFile, connection); |
216 | } catch (IOException e) { |
217 | RVisualisationPlugin.log(IStatus.ERROR, |
218 | "Could not create temporary raster graphic file. " |
219 | + e.getClass().getCanonicalName()); |
220 | } |
221 | |
222 | // generate vector image |
223 | try { |
224 | temporaryVectorGraphicFile = |
225 | File.createTempFile("pcm_pic", ".pdf"); |
226 | temporaryVectorGraphicFile.deleteOnExit(); |
227 | generateVectorGraphic(temporaryVectorGraphicFile, connection); |
228 | } catch (IOException e) { |
229 | RVisualisationPlugin.log(IStatus.ERROR, |
230 | "Could not create temporary vector graphic file. " |
231 | + e.getClass().getCanonicalName()); |
232 | } |
233 | } |
234 | |
235 | |
236 | /**Returns the R commands which generate a line legend in R. |
237 | * @return The necessary R commands. |
238 | */ |
239 | protected String generateLinesLegend() { |
240 | if (legendPosition == LegendPosition.none) { |
241 | return ""; |
242 | } |
243 | |
244 | int pos = 0; |
245 | String lines = "c("; |
246 | String legend = "c("; |
247 | |
248 | for (String id : getDataSeries()) { |
249 | String name = getName(id); |
250 | String sep = (pos == 0 ? "" : ", "); |
251 | lines += sep + (pos + 1); |
252 | legend += sep + "\"" + name + "\""; |
253 | pos++; |
254 | } |
255 | lines += ")"; |
256 | legend += ")"; |
257 | return "legend(\"" + legendPosition + "\", " + legend + ", lty=" |
258 | + lines + ", bg='white')\n"; |
259 | } |
260 | |
261 | /**Returns the R commands which generate a color legend in R. |
262 | * @return The necessary R commads. |
263 | */ |
264 | protected String generateColorsLegend() { |
265 | if (legendPosition == LegendPosition.none) { |
266 | return ""; |
267 | } |
268 | |
269 | int pos = 0; |
270 | String fill = "c("; |
271 | String legend = "c("; |
272 | |
273 | for (String id : getDataSeries()) { |
274 | String name = getName(id); |
275 | String sep = (pos == 0 ? "" : ", "); |
276 | fill += sep + "\"" + colors[pos % colors.length] + "\""; |
277 | legend += sep + "\"" + name + "\""; |
278 | pos++; |
279 | } |
280 | fill += ")"; |
281 | legend += ")"; |
282 | return "legend(\"" + legendPosition + "\", " + legend + ", fill=" |
283 | + fill + ", bg='white')\n"; |
284 | } |
285 | |
286 | /**Sets the legend position. |
287 | * @param newLegendPosition New position to set. |
288 | */ |
289 | public void setLegendPos(final LegendPosition newLegendPosition) { |
290 | this.legendPosition = newLegendPosition; |
291 | } |
292 | } |