|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.carbide.cpp.internal.pi.power.actions; |
|
19 |
|
20 import java.text.DecimalFormat; |
|
21 import java.util.ArrayList; |
|
22 import java.util.Arrays; |
|
23 import java.util.Comparator; |
|
24 import java.util.Hashtable; |
|
25 |
|
26 import org.eclipse.swt.SWT; |
|
27 import org.eclipse.swt.events.SelectionEvent; |
|
28 import org.eclipse.swt.events.SelectionListener; |
|
29 import org.eclipse.swt.layout.GridData; |
|
30 import org.eclipse.swt.layout.GridLayout; |
|
31 import org.eclipse.swt.widgets.Button; |
|
32 import org.eclipse.swt.widgets.Composite; |
|
33 import org.eclipse.swt.widgets.Display; |
|
34 import org.eclipse.swt.widgets.Group; |
|
35 import org.eclipse.swt.widgets.Label; |
|
36 import org.eclipse.swt.widgets.Shell; |
|
37 |
|
38 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository; |
|
39 import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser; |
|
40 import com.nokia.carbide.cpp.pi.editors.PIPageEditor; |
|
41 import com.nokia.carbide.cpp.pi.power.PowerTraceGraph; |
|
42 import com.nokia.carbide.cpp.pi.power.PwrTrace; |
|
43 |
|
44 |
|
45 public class PowerStatisticsDialog { |
|
46 |
|
47 private Shell shell; |
|
48 private GridData gridData; |
|
49 private DecimalFormat voltageFormat = new DecimalFormat(Messages.getString("PowerStatisticsDialog.voltageFormat")); //$NON-NLS-1$ |
|
50 private DecimalFormat powerFormat = new DecimalFormat(Messages.getString("PowerStatisticsDialog.powerFormat")); //$NON-NLS-1$ |
|
51 |
|
52 private PwrTrace trace; |
|
53 private double startTime; |
|
54 private double endTime; |
|
55 |
|
56 private double levelMaxPower; |
|
57 private double level90Power; |
|
58 private double level75Power; |
|
59 private double level50Power; |
|
60 private double level25Power; |
|
61 private double level10Power; |
|
62 private double levelMinPower; |
|
63 private double levelVarPower; |
|
64 |
|
65 public PowerStatisticsDialog(Display display) |
|
66 { |
|
67 int batterySize; |
|
68 float voltage; |
|
69 Group group; |
|
70 |
|
71 shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); |
|
72 shell.setText(Messages.getString("PowerStatisticsDialog.statsTitle")); //$NON-NLS-1$ |
|
73 shell.setLayout(new GridLayout(4, false)); |
|
74 |
|
75 startTime = PIPageEditor.currentPageEditor().getStartTime(); |
|
76 endTime = PIPageEditor.currentPageEditor().getEndTime(); |
|
77 |
|
78 trace = (PwrTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$ |
|
79 |
|
80 int uid = NpiInstanceRepository.getInstance().activeUid(); |
|
81 |
|
82 PowerTraceGraph graph = trace.getPowerGraph(0, uid); // since they are in lockstep, any graph will do |
|
83 |
|
84 voltage = trace.getVoltage(); |
|
85 batterySize = (int) trace.getBatterySize(); |
|
86 |
|
87 calculateStats(); |
|
88 |
|
89 group = new Group(shell, SWT.SHADOW_NONE); |
|
90 group.setText(Messages.getString("PowerStatisticsDialog.interval")); //$NON-NLS-1$ |
|
91 group.setFont(PIPageEditor.helvetica_9); |
|
92 gridData = new GridData(SWT.FILL, SWT.FILL, true, true); |
|
93 gridData.horizontalSpan = 4; |
|
94 group.setLayoutData(gridData); |
|
95 group.setLayout(new GridLayout(4, false));//new FillLayout()); |
|
96 textGrid(group, showTimeInterval(startTime, endTime), SWT.CENTER, SWT.CENTER, 4); |
|
97 |
|
98 group = new Group(shell, SWT.NONE); |
|
99 group.setText(Messages.getString("PowerStatisticsDialog.battery")); //$NON-NLS-1$ |
|
100 group.setFont(PIPageEditor.helvetica_9); |
|
101 gridData = new GridData(SWT.FILL, SWT.FILL, true, true); |
|
102 gridData.horizontalSpan = 4; |
|
103 group.setLayoutData(gridData); |
|
104 group.setLayout(new GridLayout(4, false));//new FillLayout()); |
|
105 textGrid(group, batterySize + Messages.getString("PowerStatisticsDialog.capacityVoltage2"), SWT.LEFT, SWT.CENTER, 2); //$NON-NLS-1$ //$NON-NLS-2$ |
|
106 textGrid(group, Messages.getString("PowerStatisticsDialog.capacityVoltage3") + voltageFormat.format(voltage) + Messages.getString("PowerStatisticsDialog.capacityVoltage4"), SWT.RIGHT, SWT.CENTER, 2); //$NON-NLS-1$ //$NON-NLS-2$ |
|
107 |
|
108 group = new Group(shell, SWT.NONE); |
|
109 group.setText(Messages.getString("PowerStatisticsDialog.currentSelection")); //$NON-NLS-1$ |
|
110 group.setFont(PIPageEditor.helvetica_9); |
|
111 gridData = new GridData(SWT.FILL, SWT.FILL, true, true); |
|
112 gridData.horizontalSpan = 4; |
|
113 group.setLayoutData(gridData); |
|
114 group.setLayout(new GridLayout(4, false));//new FillLayout()); |
|
115 |
|
116 double meanPower; |
|
117 double meanEnergy; |
|
118 long meanLife; |
|
119 |
|
120 meanPower = graph.getAverageConsumption(); |
|
121 meanEnergy = graph.getCumulativeConsumption(); |
|
122 |
|
123 if (meanPower == 0) |
|
124 meanLife = 0; |
|
125 else |
|
126 meanLife = Math.round((float) graph.getBatterySize() * 3600 * graph.getVoltage() / meanPower); |
|
127 |
|
128 textGrid(group, Messages.getString("PowerStatisticsDialog.energy1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
129 textGrid(group, (int) (meanEnergy + 0.5) |
|
130 + Messages.getString("PowerStatisticsDialog.energy2"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
131 |
|
132 long hours = meanLife / 3600; |
|
133 long minutes = (meanLife - hours * 3600) / 60; |
|
134 textGrid(group, Messages.getString("PowerStatisticsDialog.life1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
135 textGrid(group, hours + Messages.getString("PowerStatisticsDialog.life2") //$NON-NLS-1$ |
|
136 + minutes + Messages.getString("PowerStatisticsDialog.life3"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
137 |
|
138 textGrid(group, "", SWT.RIGHT, SWT.RIGHT, 4); //$NON-NLS-1$ |
|
139 |
|
140 textGrid(group, Messages.getString("PowerStatisticsDialog.avgPower1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
141 textGrid(group, powerFormat.format(meanPower) + Messages.getString("PowerStatisticsDialog.avgPower2"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
142 |
|
143 textGrid(group, Messages.getString("PowerStatisticsDialog.maxa"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
144 textGrid(group, powerFormat.format(levelMaxPower / 1000) + Messages.getString("PowerStatisticsDialog.maxb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
145 |
|
146 textGrid(group, Messages.getString("PowerStatisticsDialog.90a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
147 textGrid(group, powerFormat.format(level90Power / 1000) + Messages.getString("PowerStatisticsDialog.90b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
148 |
|
149 textGrid(group, Messages.getString("PowerStatisticsDialog.75a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
150 textGrid(group, powerFormat.format(level75Power / 1000) + Messages.getString("PowerStatisticsDialog.75b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
151 |
|
152 textGrid(group, Messages.getString("PowerStatisticsDialog.50a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
153 textGrid(group, powerFormat.format(level50Power / 1000) + Messages.getString("PowerStatisticsDialog.50b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
154 |
|
155 textGrid(group, Messages.getString("PowerStatisticsDialog.25a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
156 textGrid(group, powerFormat.format(level25Power / 1000) + Messages.getString("PowerStatisticsDialog.25b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
157 |
|
158 textGrid(group, Messages.getString("PowerStatisticsDialog.10a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
159 textGrid(group, powerFormat.format(level10Power / 1000) + Messages.getString("PowerStatisticsDialog.10b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
160 |
|
161 textGrid(group, Messages.getString("PowerStatisticsDialog.mina"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
162 textGrid(group, powerFormat.format(levelMinPower / 1000) + Messages.getString("PowerStatisticsDialog.minb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
163 |
|
164 textGrid(group, Messages.getString("PowerStatisticsDialog.variancea"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$ |
|
165 textGrid(group, powerFormat.format(levelVarPower / 1000) + Messages.getString("PowerStatisticsDialog.varianceb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$ |
|
166 |
|
167 // create the Close button |
|
168 Button close = new Button(shell, SWT.NONE); |
|
169 close.setText(Messages.getString("PowerStatisticsDialog.close")); //$NON-NLS-1$ |
|
170 gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true); |
|
171 gridData.minimumWidth = 60; |
|
172 gridData.horizontalSpan = 4; |
|
173 close.setLayoutData(gridData); |
|
174 close.addSelectionListener(new SelectionListener(){ |
|
175 |
|
176 public void widgetSelected(SelectionEvent e) { |
|
177 shell.close(); |
|
178 } |
|
179 |
|
180 public void widgetDefaultSelected(SelectionEvent e) { |
|
181 widgetSelected(e); |
|
182 } |
|
183 }); |
|
184 |
|
185 shell.pack(); |
|
186 shell.open(); |
|
187 |
|
188 while (!shell.isDisposed()) { |
|
189 if (!shell.getDisplay().readAndDispatch()) { |
|
190 shell.getDisplay().sleep(); |
|
191 } |
|
192 } |
|
193 } |
|
194 |
|
195 private void textGrid(Composite parent, String text, int labelStyle, int gridStyle, int gridSpan) |
|
196 { |
|
197 Label label = new Label(parent, labelStyle); |
|
198 label.setFont(PIPageEditor.helvetica_9); |
|
199 label.setText(text); |
|
200 gridData = new GridData(SWT.FILL, gridStyle, true, true); |
|
201 gridData.horizontalSpan = gridSpan; |
|
202 label.setLayoutData(gridData); |
|
203 } |
|
204 |
|
205 public void dispose() |
|
206 { |
|
207 if (this.shell != null) { |
|
208 if (!this.shell.isDisposed()) { |
|
209 this.shell.close(); |
|
210 } |
|
211 this.shell.dispose(); |
|
212 } |
|
213 |
|
214 this.shell = null; |
|
215 } |
|
216 |
|
217 private static String showTimeInterval(double startTime, double endTime) |
|
218 { |
|
219 return ProfileVisualiser.timeFormat.format(startTime) |
|
220 + Messages.getString("PowerStatisticsDialog.interval1") + ProfileVisualiser.timeFormat.format(endTime) //$NON-NLS-1$ |
|
221 + Messages.getString("PowerStatisticsDialog.interval2") + ProfileVisualiser.timeFormat.format(endTime - startTime) //$NON-NLS-1$ |
|
222 + Messages.getString("PowerStatisticsDialog.interval3"); //$NON-NLS-1$ |
|
223 } |
|
224 |
|
225 private class PowerStat { |
|
226 public double power; |
|
227 public int count; |
|
228 |
|
229 PowerStat(double power) { |
|
230 this.power = power; |
|
231 this.count = 0; |
|
232 } |
|
233 |
|
234 PowerStat(double power, int count) { |
|
235 this.power = power; |
|
236 this.count = count; |
|
237 } |
|
238 } |
|
239 |
|
240 private void calculateStats() |
|
241 { |
|
242 PowerStat powerStat; |
|
243 Object[] powerLevelArray; |
|
244 ArrayList<PowerStat> powerLevel = new ArrayList<PowerStat>(); |
|
245 Hashtable<Double,PowerStat> powerStatHash = new Hashtable<Double,PowerStat>(); |
|
246 double sumOfSquares = 0.0; |
|
247 double sum = 0.0; |
|
248 int count = 0; |
|
249 |
|
250 int selStart = (int)(this.startTime * 1000 + 0.0005) + 1; |
|
251 int selEnd = (int)(this.endTime * 1000 + 0.0005); |
|
252 int totalCount = selEnd - selStart + 1; |
|
253 |
|
254 levelVarPower = 0.0; |
|
255 |
|
256 if (selEnd < trace.getFirstSampleNumber() || selStart > selEnd) |
|
257 { |
|
258 powerLevelArray = new PowerStat[1]; |
|
259 powerLevelArray[0] = new PowerStat(0.0, 1); |
|
260 totalCount = 1; |
|
261 } |
|
262 else |
|
263 { |
|
264 PowerTraceGraph graph = trace.getPowerGraph(0, NpiInstanceRepository.getInstance().activeUid()); // since graphs are in lockstep, any will do |
|
265 |
|
266 int index = graph.timeIndex(selStart); |
|
267 |
|
268 // count time before the first sample as a bunch of zeros |
|
269 if (selStart < trace.getFirstSampleNumber()) { |
|
270 count = trace.getFirstSampleNumber() - selStart; |
|
271 powerStat = new PowerStat(0, count); |
|
272 powerLevel.add(powerStat); |
|
273 powerStatHash.put(0.0, powerStat); |
|
274 index = 0; |
|
275 } |
|
276 |
|
277 int[] sampleTimes = trace.getSampleTimes(); |
|
278 int[] ampValues = trace.getAmpValues(); |
|
279 |
|
280 for (int j = index; j < sampleTimes.length; j++) |
|
281 { |
|
282 int time = sampleTimes[j] + 1; |
|
283 if (time < selStart) |
|
284 time = selStart; |
|
285 |
|
286 int nextTime = j == sampleTimes.length - 1 ? Integer.MAX_VALUE : sampleTimes[j + 1]; |
|
287 |
|
288 count = Math.min(nextTime - time + 1, selEnd - time + 1); |
|
289 double power = ampValues[j] * this.trace.getVoltage() * 1000.0; |
|
290 sumOfSquares += power * power * count; |
|
291 sum += power * count; |
|
292 time += count; |
|
293 |
|
294 powerStat = powerStatHash.get(power); |
|
295 if (powerStat == null) { |
|
296 powerStat = new PowerStat(power,count); |
|
297 powerLevel.add(powerStat); |
|
298 powerStatHash.put(power, powerStat); |
|
299 } else { |
|
300 powerStat.count += count; |
|
301 } |
|
302 |
|
303 if (time > selEnd) |
|
304 break; |
|
305 } |
|
306 |
|
307 powerLevelArray = powerLevel.toArray(); |
|
308 Arrays.sort(powerLevelArray, new Comparator<Object>() { |
|
309 |
|
310 public int compare(Object o1, Object o2) { |
|
311 if (!(o1 instanceof PowerStat) || !(o2 instanceof PowerStat)) |
|
312 return 0; |
|
313 |
|
314 double powerDiff = ((PowerStat)o1).power - ((PowerStat)o2).power; |
|
315 |
|
316 return powerDiff == 0.0 ? 0 : (powerDiff < 0.0 ? -1 : 1); |
|
317 } |
|
318 }); |
|
319 } |
|
320 |
|
321 levelMaxPower = ((PowerStat) powerLevelArray[powerLevelArray.length - 1]).power; |
|
322 |
|
323 level90Power = getPowerLevel(powerLevelArray, (totalCount * 90) / 100); |
|
324 level75Power = getPowerLevel(powerLevelArray, (totalCount * 75) / 100); |
|
325 level50Power = getPowerLevel(powerLevelArray, (totalCount * 50) / 100); |
|
326 level25Power = getPowerLevel(powerLevelArray, (totalCount * 25) / 100); |
|
327 level10Power = getPowerLevel(powerLevelArray, (totalCount * 10) / 100); |
|
328 |
|
329 levelMinPower = ((PowerStat) powerLevelArray[0]).power; |
|
330 |
|
331 levelVarPower = (sumOfSquares - (sum * sum)/totalCount)/totalCount; |
|
332 } |
|
333 |
|
334 // given array powerLevelArray of PowerStat elements (each representing PowerStat.count entries), find |
|
335 // power value of entry number index |
|
336 private double getPowerLevel(Object[] powerLevelArray, int index) |
|
337 { |
|
338 if (index == 0 || powerLevelArray == null || powerLevelArray.length == 0) |
|
339 return 0.0; |
|
340 |
|
341 for (int i = 0; (i < powerLevelArray.length) && (powerLevelArray[i] instanceof PowerStat); i++) { |
|
342 PowerStat powerStat = (PowerStat) powerLevelArray[i]; |
|
343 if (index <= powerStat.count) |
|
344 return powerStat.power; |
|
345 index -= powerStat.count; |
|
346 } |
|
347 |
|
348 return 0.0; |
|
349 } |
|
350 } |