File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\util\ChartUtil.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.util;
25
26 import hudson.model.AbstractBuild;
27 import hudson.tasks.junit.History;
28 import org.jfree.chart.JFreeChart;
29 import org.jfree.chart.axis.NumberAxis;
30 import org.jfree.data.category.CategoryDataset;
31 import org.kohsuke.stapler.StaplerRequest;
32 import org.kohsuke.stapler.StaplerResponse;
33
34 import java.awt.Font;
35 import java.io.IOException;
36
37 /**
38 * Chart generation utility code around JFreeChart.
39 *
40 * @see StackedAreaRenderer2
41 * @see DataSetBuilder
42 * @see ShiftedCategoryAxis
43 * @author Kohsuke Kawaguchi
44 */
45 public class ChartUtil {
46 /**
47 * Can be used as a graph label. Only displays numbers.
48 */
49 public static final class NumberOnlyBuildLabel implements Comparable<NumberOnlyBuildLabel> {
50 public final AbstractBuild build;
51
52 public NumberOnlyBuildLabel(AbstractBuild build) {
53 this.build = build;
54 }
55
56 public int compareTo(NumberOnlyBuildLabel that) {
57 return this.build.number-that.build.number;
58 }
59
60 @Override
61 public boolean equals(Object o) {
62 if(!(o instanceof NumberOnlyBuildLabel)) return false;
63 NumberOnlyBuildLabel that = (NumberOnlyBuildLabel) o;
64 return build==that.build;
65 }
66
67 @Override
68 public int hashCode() {
69 return build.hashCode();
70 }
71
72 @Override
73 public String toString() {
74 return build.getDisplayName();
75 }
76 }
77
78 /**
79 * @deprecated
80 * Use {@code awtProblemCause!=null} instead. As of 1.267.
81 */
82 public static boolean awtProblem = false;
83
84 /**
85 * See issue 93. Detect an error in X11 and handle it gracefully.
86 */
87 public static Throwable awtProblemCause = null;
88
89 /**
90 * Generates the graph in PNG format and sends that to the response.
91 *
92 * @param defaultSize
93 * The size of the picture to be generated. These values can be overridden
94 * by the query paramter 'width' and 'height' in the request.
95 * @deprecated as of 1.320
96 * Bind {@link Graph} to the URL space. See {@link History} as an example (note that doing so involves
97 * a bit of URL structure change.)
98 */
99 public static void generateGraph(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, Area defaultSize) throws IOException {
100 generateGraph(req,rsp,chart,defaultSize.width, defaultSize.height);
101 }
102
103 /**
104 * Generates the graph in PNG format and sends that to the response.
105 *
106 * @param defaultW
107 * @param defaultH
108 * The size of the picture to be generated. These values can be overridden
109 * by the query paramter 'width' and 'height' in the request.
110 * @deprecated as of 1.320
111 * Bind {@link Graph} to the URL space. See {@link History} as an example (note that doing so involves
112 * a bit of URL structure change.)
113 */
114 public static void generateGraph(StaplerRequest req, StaplerResponse rsp, final JFreeChart chart, int defaultW, int defaultH) throws IOException {
115 new Graph(-1,defaultW,defaultH) {
116 protected JFreeChart createGraph() {
117 return chart;
118 }
119 }.doPng(req,rsp);
120 }
121
122 /**
123 * Generates the clickable map info and sends that to the response.
124 *
125 * @deprecated as of 1.320
126 * Bind {@link Graph} to the URL space. See {@link History} as an example (note that doing so involves
127 * a bit of URL structure change.)
128 */
129 public static void generateClickableMap(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, Area defaultSize) throws IOException {
130 generateClickableMap(req,rsp,chart,defaultSize.width,defaultSize.height);
131 }
132
133 /**
134 * Generates the clickable map info and sends that to the response.
135 *
136 * @deprecated as of 1.320
137 * Bind {@link Graph} to the URL space. See {@link History} as an example (note that doing so involves
138 * a bit of URL structure change.)
139 */
140 public static void generateClickableMap(StaplerRequest req, StaplerResponse rsp, final JFreeChart chart, int defaultW, int defaultH) throws IOException {
141 new Graph(-1,defaultW,defaultH) {
142 protected JFreeChart createGraph() {
143 return chart;
144 }
145 }.doMap(req,rsp);
146 }
147
148 /**
149 * Adjusts the Y-axis so that abnormally large value won't spoil the whole chart
150 * by making everything look virtually 0.
151 *
152 * <p>
153 * The algorithm is based on <a href="http://en.wikipedia.org/wiki/Chebyshev%27s_inequality">Chebyshev's inequality</a>,
154 * which states that given any number sequence, nore more than 1/(N^2) values are more than N x stddev away
155 * from the average.
156 *
157 * <p>
158 * So the algorithm is to set Y-axis range so that we can see all data points that are within N x stddev
159 * of the average. Most of the time, Cebyshev's inequality is very conservative, so it shouldn't do
160 * much harm.
161 *
162 * <p>
163 * When the algorithm does kick in, however, we can kick out at most 1 in N^2 data points.
164 * (So for example if N=3 then we can "fix" the graph as long as we only have less than 1/(3*3)=11.111...% bad data.
165 *
166 * <p>
167 * Also see issue #1246.
168 */
169 public static void adjustChebyshev(CategoryDataset dataset, NumberAxis yAxis) {
170 // first compute E(X) and Var(X)
171 double sum=0,sum2=0;
172
173 final int nColumns = dataset.getColumnCount();
174 final int nRows = dataset.getRowCount();
175 for (int i=0; i<nRows; i++ ) {
176 Comparable rowKey = dataset.getRowKey(i);
177 for( int j=0; j<nColumns; j++) {
178 Comparable columnKey = dataset.getColumnKey(j);
179
180 double n = dataset.getValue(rowKey,columnKey).doubleValue();
181 sum += n;
182 sum2 +=n*n;
183 }
184 }
185
186 double average = sum/(nColumns*nRows);
187 double stddev = Math.sqrt(sum2/(nColumns*nRows)-average*average);
188
189 double rangeMin = average-stddev*CHEBYSHEV_N;
190 double rangeMax = average+stddev*CHEBYSHEV_N;
191
192 // now see if there are any data points that fall outside (rangeMin,rangeMax)
193 boolean found = false;
194 double min=0,max=0;
195 for (int i=0; i<nRows; i++ ) {
196 Comparable rowKey = dataset.getRowKey(i);
197 for( int j=0; j<nColumns; j++) {
198 Comparable columnKey = dataset.getColumnKey(j);
199
200 double n = dataset.getValue(rowKey,columnKey).doubleValue();
201 if(n<rangeMin || rangeMax<n) {
202 found = true;
203 continue; // ignore this value
204 }
205
206 min = Math.min(min,n);
207 max = Math.max(max,n);
208 }
209 }
210
211 if(!found)
212 return; // no adjustment was necessary
213
214 // some values fell outside the range, so adjust the Y-axis
215
216 // if we are ever to extend this method to handle negative value ranges correctly,
217 // the code after this needs modifications
218
219 min = Math.min(0,min); // always include 0 in the graph
220 max += yAxis.getUpperMargin()*(max-min);
221
222 yAxis.setRange(min,max);
223 }
224
225 public static double CHEBYSHEV_N = 3;
226
227 static {
228 try {
229 new Font("SansSerif",Font.BOLD,18).toString();
230 } catch (Throwable t) {
231 awtProblemCause = t;
232 awtProblem = true;
233 }
234 }
235 }
236