Package de.lmu.ifi.dbs.elki.visualization

Source Code of de.lmu.ifi.dbs.elki.visualization.ExportVisualizations

package de.lmu.ifi.dbs.elki.visualization;

/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures

Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.apache.batik.util.SVGConstants;

import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultHandler;
import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter.FileType;
import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
import de.lmu.ifi.dbs.elki.visualization.projector.Projector;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil;

/**
* Class that automatically generates all visualizations and exports them into
* SVG files.
*
* @author Erich Schubert
*/
// TODO: make more parameterizable, wrt. what to skip
public class ExportVisualizations implements ResultHandler {
  /**
   * Get a logger for this class.
   */
  protected final static Logging logger = Logging.getLogger(ExportVisualizations.class);

  /**
   * Parameter to specify the canvas ratio
   * <p>
   * Key: {@code -vis.ratio}
   * </p>
   * <p>
   * Default value: 1.33
   * </p>
   */
  public static final OptionID RATIO_ID = OptionID.getOrCreateOptionID("vis.ratio", "The width/heigh ratio of the output.");

  /**
   * Parameter to specify the output folder
   * <p>
   * Key: {@code -vis.output}
   * </p>
   */
  public static final OptionID FOLDER_ID = OptionID.getOrCreateOptionID("vis.output", "The output folder.");

  /**
   * Output folder
   */
  File output;

  /**
   * Visualization manager.
   */
  VisualizerParameterizer manager;

  /**
   * Ratio for canvas
   */
  double ratio;

  /**
   * Base result
   */
  HierarchicalResult baseResult = null;

  /**
   * Visualizer context
   */
  VisualizerContext context = null;

  /**
   * Output counter
   */
  int counter = 0;

  /**
   * Constructor.
   *
   * @param output Output folder
   * @param manager Parameterizer
   * @param ratio Canvas ratio
   */
  protected ExportVisualizations(File output, VisualizerParameterizer manager, double ratio) {
    super();
    this.output = output;
    this.manager = manager;
    this.ratio = ratio;
  }

  @Override
  public void processNewResult(HierarchicalResult baseResult, Result newResult) {
    if(output.isFile()) {
      throw new AbortException("Output folder cannot be an existing file.");
    }
    if(!output.exists()) {
      if(!output.mkdirs()) {
        throw new AbortException("Could not create output directory.");
      }
    }
    if(this.baseResult != baseResult) {
      this.baseResult = baseResult;
      context = null;
      counter = 0;
      logger.verbose("Note: Reusing visualization exporter for more than one result is untested.");
    }
    if(context == null) {
      context = manager.newContext(baseResult);
    }

    // Projected visualizations
    ArrayList<Projector> projectors = ResultUtil.filterResults(baseResult, Projector.class);
    for(Projector proj : projectors) {
      // TODO: allow selecting individual projections only.
      Collection<PlotItem> items = proj.arrange();
      for(PlotItem item : items) {
        processItem(item);
      }
    }
    ResultHierarchy hier = baseResult.getHierarchy();
    ArrayList<VisualizationTask> tasks = ResultUtil.filterResults(baseResult, VisualizationTask.class);
    for(VisualizationTask task : tasks) {
      boolean isprojected = false;
      for(Result parent : hier.getParents(task)) {
        if(parent instanceof Projector) {
          isprojected = true;
          break;
        }
      }
      if(isprojected) {
        continue;
      }
      PlotItem pi = new PlotItem(ratio, 1.0, null);
      pi.add(task);
      processItem(pi);
    }
  }

  private void processItem(PlotItem item) {
    final double height = 1;
    final double width = ratio * height;
    // Descend into subitems
    for(Iterator<PlotItem> iter = item.subitems.iterator(); iter.hasNext();) {
      PlotItem subitem = iter.next();
      processItem(subitem);
    }
    if(item.taskSize() <= 0) {
      return;
    }
    item.sort();

    SVGPlot svgp = new SVGPlot();
    svgp.getRoot().setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, "20cm");
    svgp.getRoot().setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, (20 / ratio) + "cm");
    svgp.getRoot().setAttribute(SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, "0 0 " + width + " " + height);

    ArrayList<Visualization> layers = new ArrayList<Visualization>();
    for(Iterator<VisualizationTask> iter = item.tasks.iterator(); iter.hasNext();) {
      VisualizationTask task = iter.next();
      {
        Boolean dis = task.getGenerics(VisualizationTask.META_NODETAIL, Boolean.class);
        if(dis != null && dis == true) {
          continue;
        }
      }
      {
        Boolean dis = task.getGenerics(VisualizationTask.META_NOEXPORT, Boolean.class);
        if(dis != null && dis == true) {
          continue;
        }
      }
      if(!VisualizerUtil.isVisible(task)) {
        continue;
      }
      try {
        Visualization v = task.getFactory().makeVisualization(task.clone(svgp, context, item.proj, width, height));
        layers.add(v);
      }
      catch(Exception e) {
        if(Logging.getLogger(task.getFactory().getClass()).isDebugging()) {
          LoggingUtil.exception("Visualization failed.", e);
        }
        else {
          LoggingUtil.warning("Visualizer " + task.getFactory().getClass().getName() + " failed - enable debugging to see details.");
        }
      }
    }
    if(layers.size() <= 0) {
      return;
    }
    for(Visualization layer : layers) {
      if(layer.getLayer() != null) {
        svgp.getRoot().appendChild(layer.getLayer());
      }
      else {
        LoggingUtil.warning("NULL layer seen.");
      }
    }
    svgp.updateStyleElement();

    // TODO: generate names...
    File outname = new File(output, "plot-" + counter + ".svg");
    try {
      svgp.saveAsSVG(outname);
    }
    catch(Exception e) {
      logger.warning("Export of visualization failed.", e);
    }
    for(Visualization layer : layers) {
      layer.destroy();
    }
    counter++;
  }

  /**
   * Parameterization class
   *
   * @author Erich Schubert
   *
   * @apiviz.exclude
   */
  public static class Parameterizer extends AbstractParameterizer {
    /**
     * Visualization manager.
     */
    VisualizerParameterizer manager;

    /**
     * Output folder
     */
    File output;

    /**
     * Ratio for canvas
     */
    double ratio;

    @Override
    protected void makeOptions(Parameterization config) {
      super.makeOptions(config);
      FileParameter outputP = new FileParameter(FOLDER_ID, FileType.OUTPUT_FILE);
      if(config.grab(outputP)) {
        output = outputP.getValue();
      }

      DoubleParameter ratioP = new DoubleParameter(RATIO_ID, new GreaterConstraint(0.0), 1.33);
      if(config.grab(ratioP)) {
        ratio = ratioP.getValue();
      }

      manager = config.tryInstantiate(VisualizerParameterizer.class);
    }

    @Override
    protected ExportVisualizations makeInstance() {
      return new ExportVisualizations(output, manager, ratio);
    }
  }
}
TOP

Related Classes of de.lmu.ifi.dbs.elki.visualization.ExportVisualizations

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.