45
45
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
46
46
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
47
47
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
48
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
48
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints;
49
49
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
50
50
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
51
51
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
113
113
public void processNewResult(HierarchicalResult baseResult, Result result) {
114
114
// Find a style result to visualize:
115
115
Collection<StyleResult> styleres = ResultUtil.filterResults(result, StyleResult.class);
116
for (StyleResult c : styleres) {
116
for(StyleResult c : styleres) {
117
117
Collection<HistogramProjector<?>> ps = ResultUtil.filterResults(baseResult, HistogramProjector.class);
118
for (HistogramProjector<?> p : ps) {
118
for(HistogramProjector<?> p : ps) {
120
120
final VisualizationTask task = new VisualizationTask(CNAME, c, p.getRelation(), this);
121
121
task.level = VisualizationTask.LEVEL_DATA;
196
196
// Styling policy
197
197
final StylingPolicy spol = style.getStylingPolicy();
198
198
final ClassStylingPolicy cspol;
199
if (spol instanceof ClassStylingPolicy) {
199
if(spol instanceof ClassStylingPolicy) {
200
200
cspol = (ClassStylingPolicy) spol;
204
205
// TODO also use min style?
212
213
final int cols = numc + 1;
213
214
DoubleArrayStaticHistogram histogram = new DoubleArrayStaticHistogram(settings.bins, -.5, .5, cols);
216
for (int snum = 0; snum < numc; snum++) {
217
for(int snum = 0; snum < numc; snum++) {
217
218
double[] inc = new double[cols];
219
220
inc[snum + 1] = frac;
220
for (DBIDIter iter = cspol.iterateClass(snum + off); iter.valid(); iter.advance()) {
221
if (!sample.getSample().contains(iter)) {
221
for(DBIDIter iter = cspol.iterateClass(snum + off); iter.valid(); iter.advance()) {
222
if(!sample.getSample().contains(iter)) {
222
223
continue; // TODO: can we test more efficiently than this?
225
226
double pos = proj.fastProjectDataToRenderSpace(relation.get(iter)) / Projection.SCALE;
226
227
histogram.increment(pos, inc);
227
} catch (ObjectNotFoundException e) {
229
catch(ObjectNotFoundException e) {
228
230
// Ignore. The object was probably deleted from the database
233
236
// Actual data distribution.
234
237
double[] inc = new double[cols];
236
for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
239
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
237
240
double pos = proj.fastProjectDataToRenderSpace(relation.get(iditer)) / Projection.SCALE;
238
241
histogram.increment(pos, inc);
241
244
// for scaling, get the maximum occurring value in the bins:
242
for (DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
243
for (double val : iter.getValue()) {
245
for(DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
246
for(double val : iter.getValue()) {
255
258
// draw axes that are non-trivial
256
259
final int dimensionality = RelationUtil.dimensionality(relation);
257
260
double orig = proj.fastProjectScaledToRender(new Vector(dimensionality));
258
for (int d = 0; d < dimensionality; d++) {
261
for(int d = 0; d < dimensionality; d++) {
259
262
Vector v = new Vector(dimensionality);
261
264
// projected endpoint of axis
262
265
double ax = proj.fastProjectScaledToRender(v);
263
if (ax < orig || ax > orig) {
266
if(ax < orig || ax > orig) {
264
267
final double left = (orig / Projection.SCALE + 0.5) * xsize;
265
268
final double right = (ax / Projection.SCALE + 0.5) * xsize;
266
269
SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getScale(d), left, ysize, right, ysize, SVGSimpleLinearAxis.LabelStyle.RIGHTHAND, style.getStyleLibrary());
269
} catch (CSSNamingConflict e) {
273
catch(CSSNamingConflict e) {
270
274
LoggingUtil.exception("CSS class exception in axis class.", e);
274
if (!settings.curves) {
275
for (DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
278
if(!settings.curves) {
279
for(DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
276
280
double lpos = xscale.getScaled(iter.getLeft());
277
281
double rpos = xscale.getScaled(iter.getRight());
278
282
double stack = 0.0;
279
283
final int start = numc > 0 ? 1 : 0;
280
for (int key = start; key < cols; key++) {
284
for(int key = start; key < cols; key++) {
281
285
double val = yscale.getScaled(iter.getValue()[key]);
282
286
Element row = SVGUtil.svgRect(svgp.getDocument(), xsize * lpos, ysize * (1 - (val + stack)), xsize * (rpos - lpos), ysize * val);
283
287
stack = stack + val;
285
289
layer.appendChild(row);
289
294
double left = xscale.getScaled(histogram.getCoverMinimum());
290
295
double right = left;
292
297
SVGPath[] paths = new SVGPath[cols];
293
298
double[] lasty = new double[cols];
294
for (int i = 0; i < cols; i++) {
299
for(int i = 0; i < cols; i++) {
295
300
paths[i] = new SVGPath(xsize * left, ysize * 1);
299
304
// draw histogram lines
300
for (DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
305
for(DoubleArrayStaticHistogram.Iter iter = histogram.iter(); iter.valid(); iter.advance()) {
301
306
left = xscale.getScaled(iter.getLeft());
302
307
right = xscale.getScaled(iter.getRight());
303
for (int i = 0; i < cols; i++) {
308
for(int i = 0; i < cols; i++) {
304
309
double val = yscale.getScaled(iter.getValue()[i]);
305
if (lasty[i] > val || lasty[i] < val) {
310
if(lasty[i] > val || lasty[i] < val) {
306
311
paths[i].lineTo(xsize * left, ysize * (1 - lasty[i]));
307
312
paths[i].lineTo(xsize * left, ysize * (1 - val));
308
313
paths[i].lineTo(xsize * right, ysize * (1 - val));
313
318
// close and insert all lines.
314
for (int i = 0; i < cols; i++) {
319
for(int i = 0; i < cols; i++) {
316
321
paths[i].lineTo(xsize * right, ysize * (1 - lasty[i]));
318
323
paths[i].lineTo(xsize * right, ysize * 1);
333
338
ColorLibrary colors = style.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
335
340
CSSClass allInOne = new CSSClass(svgp, BIN + -1);
336
if (!settings.curves) {
341
if(!settings.curves) {
337
342
allInOne.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
338
343
allInOne.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, 1.0);
340
346
allInOne.setStatement(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
341
347
allInOne.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
342
348
allInOne.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
344
350
svgp.addCSSClassOrLogError(allInOne);
346
for (int clusterID = 0; clusterID < numc; clusterID++) {
352
for(int clusterID = 0; clusterID < numc; clusterID++) {
347
353
CSSClass bin = new CSSClass(svgp, BIN + clusterID);
349
if (!settings.curves) {
355
if(!settings.curves) {
350
356
bin.setStatement(SVGConstants.CSS_FILL_PROPERTY, colors.getColor(clusterID));
352
359
bin.setStatement(SVGConstants.CSS_STROKE_PROPERTY, colors.getColor(clusterID));
353
360
bin.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
354
361
bin.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
399
406
protected void makeOptions(Parameterization config) {
400
407
super.makeOptions(config);
401
408
Flag curvesF = new Flag(STYLE_CURVES_ID);
402
if (config.grab(curvesF)) {
409
if(config.grab(curvesF)) {
403
410
curves = curvesF.isTrue();
405
412
IntParameter binsP = new IntParameter(HISTOGRAM_BINS_ID, DEFAULT_BINS);
406
binsP.addConstraint(new GreaterEqualConstraint(2));
407
if (config.grab(binsP)) {
413
binsP.addConstraint(CommonConstraints.GREATER_THAN_ONE_INT);
414
if(config.grab(binsP)) {
408
415
bins = binsP.intValue();