/*
* RapidMiner
*
* Copyright (C) 2001-2014 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* 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/.
*/
package com.rapidminer.gui.new_plotter.engine.jfreechart;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.SeriesException;
import org.jfree.data.statistics.DefaultMultiValueCategoryDataset;
import org.jfree.data.statistics.DefaultStatisticalCategoryDataset;
import org.jfree.data.xy.DefaultIntervalXYDataset;
import org.jfree.data.xy.DefaultTableXYDataset;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import com.rapidminer.gui.new_plotter.ChartPlottimeException;
import com.rapidminer.gui.new_plotter.configuration.DefaultDimensionConfig;
import com.rapidminer.gui.new_plotter.configuration.DimensionConfig.PlotDimension;
import com.rapidminer.gui.new_plotter.configuration.GroupCellKey;
import com.rapidminer.gui.new_plotter.configuration.PlotConfiguration;
import com.rapidminer.gui.new_plotter.configuration.SeriesFormat.IndicatorType;
import com.rapidminer.gui.new_plotter.configuration.ValueSource;
import com.rapidminer.gui.new_plotter.configuration.ValueSource.SeriesUsageType;
import com.rapidminer.gui.new_plotter.data.DimensionConfigData;
import com.rapidminer.gui.new_plotter.data.GroupCellData;
import com.rapidminer.gui.new_plotter.data.GroupCellKeyAndData;
import com.rapidminer.gui.new_plotter.data.GroupCellSeriesData;
import com.rapidminer.gui.new_plotter.data.PlotInstance;
import com.rapidminer.gui.new_plotter.data.ValueSourceData;
import com.rapidminer.gui.new_plotter.utility.ValueRange;
import com.rapidminer.tools.I18N;
import com.rapidminer.tools.container.Pair;
/**
* Helper class for converting data delivered by {@link ValueSource}s into datasets usable by
* JFreeChart.
*
* @author Marius Helf
*
*/
public class ChartDatasetFactory {
/**
* private ctor, cause this is a static-only class
*/
private ChartDatasetFactory() {
}
/**
* @param valueSource
* @param plotInstance
* @param autoWidthFraction
* If this value is greater than 0, an auto width for the intervals is calculated
* such that the intervals nearest to each other touch. This value is then multiplied
* with the value of autoWidthFtraction. If unset, the intervals have width 0.
* @param allowDuplicates
* @param sortByDomain
* if true, the data is sorted by domain values (useful for bar and area charts)
* @return
* @throws ChartPlottimeException
*/
public static XYSeriesCollection createXYSeriesCollection(ValueSource valueSource, PlotInstance plotInstance, double autoWidthFraction, boolean allowDuplicates,
boolean sortByDomain) throws ChartPlottimeException {
XYSeriesCollection xyDataset = new XYSeriesCollection();
if (autoWidthFraction > 0) {
xyDataset.setAutoWidth(true);
} else {
xyDataset.setAutoWidth(false);
xyDataset.setIntervalWidth(0);
}
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
// Loop over group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
String seriesName = generateSeriesName(valueSource, groupCellKey, plotInstance.getCurrentPlotConfigurationClone());
XYSeries series = new XYSeries(seriesName, sortByDomain, allowDuplicates);
Map<PlotDimension, double[]> dataForUsageType = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
int rowCount = dataForUsageType.get(PlotDimension.DOMAIN).length;
double[] xValues = dataForUsageType.get(PlotDimension.DOMAIN);
double[] yValues = dataForUsageType.get(PlotDimension.VALUE);
try {
// Loop over rows and add data to series
for (int row = 0; row < rowCount; ++row) {
double x = xValues[row];
double y = yValues[row];
if (!Double.isNaN(x)) {
series.add(x, y);
}
}
} catch (SeriesException e) {
throw new ChartPlottimeException("duplicate_value", valueSource.toString(), PlotDimension.DOMAIN.getName());
}
xyDataset.addSeries(series);
}
// intervals should not touch each other, so decrease auto width.
if (xyDataset.getIntervalWidth() > 0) {
xyDataset.setIntervalWidth(xyDataset.getIntervalWidth() * autoWidthFraction);
}
return xyDataset;
}
/**
* Creates a dataset which supports custom intervals on both axes.
*
* Expects a grouping on the domain axis.
*
* @throws ChartPlottimeException
*/
public static DefaultIntervalXYDataset createDefaultIntervalXYDataset(ValueSource valueSource, PlotInstance plotInstance, boolean createRangeIntervals)
throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultIntervalXYDataset intervalDataset = new DefaultIntervalXYDataset();
DefaultDimensionConfig domainConfig = valueSource.getDomainConfig();
DimensionConfigData domainConfigData = plotInstance.getPlotData().getDimensionConfigData(domainConfig);
// Loop all group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
// create series name
GroupCellKey groupCellKeyClone = (GroupCellKey) groupCellKey.clone();
groupCellKeyClone.removeRangeForDimension(PlotDimension.DOMAIN); // legend does not need X-group
String seriesName = generateSeriesName(valueSource, groupCellKeyClone, plotInstance.getCurrentPlotConfigurationClone());
List<ValueRange> domainValueGroups = domainConfigData.getGroupingModel();
// Loop all rows and add data to series.
// Remember that by definition one row in the groupCellData corresponds
// to one group in xValueGroups (if the x-axis is grouped, which should
// always be the case in this function).
final int domainValueIdx = 0;
final int domainLowerIdx = 1;
final int domainUpperIdx = 2;
final int rangeValueIdx = 3;
final int rangeLowerIdx = 4;
final int rangeUpperIdx = 5;
Map<PlotDimension, double[]> dataForMainSeries = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
int rowCount = dataForMainSeries.get(PlotDimension.DOMAIN).length;
double[] domainValues = dataForMainSeries.get(PlotDimension.DOMAIN);
double[] rangeValues = dataForMainSeries.get(PlotDimension.VALUE);
double[] upperErrorValues = null;
double[] lowerErrorValues = null;
upperErrorValues = valueSourceData.getAbsoluteUtilityValues(groupCellKeyAndData, true);
lowerErrorValues = valueSourceData.getAbsoluteUtilityValues(groupCellKeyAndData, false);
if (createRangeIntervals && upperErrorValues == null) {
throw new ChartPlottimeException("undefined_series", valueSource.toString(), SeriesUsageType.INDICATOR_1);
}
double[][] series = new double[6][rowCount];
Iterator<ValueRange> domainGroupIterator = null;
if (domainValueGroups != null) {
domainGroupIterator = domainValueGroups.iterator();
}
double domainLower;
double domainUpper;
double domainValue;
double rangeValue;
double rangeUpper;
double rangeLower;
for (int row = 0; row < rowCount; ++row) {
domainValue = domainValues[row];
domainLower = domainValue;
domainUpper = domainValue;
if (domainGroupIterator != null) {
ValueRange currentDomainGroup = domainGroupIterator.next();
if (currentDomainGroup.definesUpperLowerBound()) {
domainLower = currentDomainGroup.getLowerBound();
domainUpper = currentDomainGroup.getUpperBound();
}
}
rangeValue = rangeValues[row];
rangeUpper = upperErrorValues != null ? upperErrorValues[row] : Double.NaN;
rangeLower = lowerErrorValues != null ? lowerErrorValues[row] : Double.NaN;
series[domainValueIdx][row] = domainValue;
series[domainLowerIdx][row] = domainLower;
series[domainUpperIdx][row] = domainUpper;
series[rangeValueIdx][row] = rangeValue;
series[rangeLowerIdx][row] = rangeLower;
series[rangeUpperIdx][row] = rangeUpper;
}
intervalDataset.addSeries(seriesName, series);
}
return intervalDataset;
}
public static CategoryDataset createDefaultCategoryDataset(ValueSource valueSource, PlotInstance plotInstance, boolean fillWithZero, boolean allowValuesLessThanZero)
throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultDimensionConfig domainConfig = valueSource.getDomainConfig();
DimensionConfigData domainConfigData = plotInstance.getPlotData().getDimensionConfigData(domainConfig);
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
// create series name
GroupCellKey groupCellKeyClone = (GroupCellKey) groupCellKey.clone();
String seriesName = generateSeriesName(valueSource, groupCellKeyClone, plotInstance.getCurrentPlotConfigurationClone());
Map<PlotDimension, double[]> dataForUsageType = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = dataForUsageType.get(PlotDimension.DOMAIN);
double[] yValues = dataForUsageType.get(PlotDimension.VALUE);
int rowCount = xValues.length;
for (int row = 0; row < rowCount; ++row) {
double xValue = xValues[row];
String xString = null;
xString = domainConfigData.getStringForValue(xValue);
Double y = yValues[row];
if (!allowValuesLessThanZero && y < 0) {
throw new ChartPlottimeException("illegal_zero_value", valueSource.toString());
}
if (xString != null) {
dataset.addValue(y, seriesName, xString);
}
}
if (fillWithZero) {
for (int row = 0; row < rowCount; ++row) {
double xValue = xValues[row];
String xString = null;
xString = domainConfigData.getStringForValue(xValue);
Number value = dataset.getValue(seriesName, xString);
if (value == null || Double.isNaN(value.doubleValue())) {
dataset.addValue(0, seriesName, xString);
}
}
}
}
return dataset;
}
public static String generateSeriesName(ValueSource valueSource, GroupCellKey groupCellKey, PlotConfiguration plotConfiguration) {
// groupCellKey.removeRangeForDimension(Dimension.X); // legend does not need X-group
String filterName = groupCellKey.getNiceString(plotConfiguration);
String seriesName = valueSource.getLabel();
StringBuilder builder = new StringBuilder();
if (seriesName == null) {
seriesName = I18N.getGUILabel("plotter.unnamed_value_label");
}
builder.append(seriesName);
if (filterName.length() != 0) {
builder.append(" [");
builder.append(filterName);
builder.append("]");
}
return builder.toString();
}
public static XYDataset createDefaultXYDataset(ValueSource valueSource, PlotInstance plotInstace) throws ChartPlottimeException {
DefaultXYDataset dataset = new DefaultXYDataset();
ValueSourceData valueSourceData = plotInstace.getPlotData().getValueSourceData(valueSource);
// assertMaxValueCountNotExceededOrThrowException(valueSourceData);
for (int seriesIdx = 0; seriesIdx < valueSourceData.getSeriesCount(); ++seriesIdx) {
addSeriesToDefaultXYDataset(valueSource, seriesIdx, plotInstace, dataset);
}
return dataset;
}
public static XYDataset createDefaultXYDataset(ValueSource valueSource, int seriesIdx, PlotInstance plotInstance) throws ChartPlottimeException {
DefaultXYDataset dataset = new DefaultXYDataset();
addSeriesToDefaultXYDataset(valueSource, seriesIdx, plotInstance, dataset);
return dataset;
}
private static void addSeriesToDefaultXYDataset(ValueSource valueSource, int seriesIdx, PlotInstance plotInstance, DefaultXYDataset dataset) throws ChartPlottimeException {
final int xIdx = 0;
final int yIdx = 1;
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
GroupCellKeyAndData groupCellKeyAndData = dataForAllGroupCells.getGroupCellKeyAndData(seriesIdx);
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
// create series name
GroupCellKey groupCellKeyClone = (GroupCellKey) groupCellKey.clone();
String seriesName = generateSeriesName(valueSource, groupCellKeyClone, plotInstance.getCurrentPlotConfigurationClone());
String differenceName = "__&%" + seriesName + "%&__";
Map<PlotDimension, double[]> mainData = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = mainData.get(PlotDimension.DOMAIN);
double[] yValues = mainData.get(PlotDimension.VALUE);
double[][] mainSeries = new double[2][xValues.length];
mainSeries[xIdx] = xValues;
mainSeries[yIdx] = yValues;
dataset.addSeries(seriesName, mainSeries);
if (valueSource.getSeriesFormat().getUtilityUsage() == IndicatorType.DIFFERENCE) {
double[] differenceValues = valueSourceData.getAbsoluteUtilityValues(groupCellKeyAndData, true);
if (differenceValues == null) {
throw new ChartPlottimeException("undefined_series", valueSource.toString(), SeriesUsageType.INDICATOR_1);
}
double[][] differenceSeries = new double[2][xValues.length];
differenceSeries[xIdx] = xValues;
differenceSeries[yIdx] = differenceValues;
dataset.addSeries(differenceName, differenceSeries);
}
}
public static DefaultTableXYDataset createDefaultTableXYDataset(ValueSource valueSource, PlotInstance plotInstance) throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultTableXYDataset dataset = new DefaultTableXYDataset();
// Loop all group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
Map<PlotDimension, double[]> dataForUsageType = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = dataForUsageType.get(PlotDimension.DOMAIN);
double[] yValues = dataForUsageType.get(PlotDimension.VALUE);
int rowCount = xValues.length;
String seriesName = generateSeriesName(valueSource, groupCellKey, plotInstance.getCurrentPlotConfigurationClone());
XYSeries series = new XYSeries(seriesName, false, false);
// Loop all rows and add data to series
double x;
double y;
for (int row = 0; row < rowCount; ++row) {
x = xValues[row];
y = yValues[row];
try {
if (!Double.isNaN(x)) {
series.add(x, y, false); // false means: do not notify. Since we are currently initializing, this is not necessary and saves us some fractions of a second
}
} catch (SeriesException e) {
throw new ChartPlottimeException("duplicate_value", valueSource.toString(), PlotDimension.DOMAIN.getName());
}
}
dataset.addSeries(series);
}
dataset.setAutoWidth(true);
return dataset;
}
public static DefaultStatisticalCategoryDataset createDefaultStatisticalCategoryDataset(ValueSource valueSource, PlotInstance plotInstance) throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset();
DefaultDimensionConfig domainConfig = valueSource.getDomainConfig();
DimensionConfigData domainConfigData = plotInstance.getPlotData().getDimensionConfigData(domainConfig);
// Loop all group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
String seriesName = generateSeriesName(valueSource, groupCellKey, plotInstance.getCurrentPlotConfigurationClone());
Map<PlotDimension, double[]> mainSeriesData = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = mainSeriesData.get(PlotDimension.DOMAIN);
double[] yValues = mainSeriesData.get(PlotDimension.VALUE);
double[] yErrorValues = valueSourceData.getAbsoluteUtilityValues(groupCellKeyAndData, true);
if (yErrorValues == null) {
throw new ChartPlottimeException("undefined_series", valueSource.toString(), SeriesUsageType.INDICATOR_1);
}
// this dataset does not support unsymmetric errors
if (groupCellData.getDataForUsageType(SeriesUsageType.INDICATOR_2) != null) {
throw new ChartPlottimeException("unsymmetric_utility_not_supported", valueSource.toString());
}
int rowCount = xValues.length;
// Loop all rows and add data to series
double xValue;
double yValue;
double yErrorValue;
String xString;
for (int row = 0; row < rowCount; ++row) {
xValue = xValues[row];
xString = domainConfigData.getStringForValue(xValue);
yValue = yValues[row];
yErrorValue = yErrorValues[row] - yValue;
dataset.add(yValue, yErrorValue, seriesName, xString);
}
}
return dataset;
}
/**
* Creates a new {@link DefaultMultiValueCategoryDataset}. Such a dataset contains a list of
* values for each datapoint of a series. For each series in valueSource a series in the dataset
* created. A datapoint in the dataset refers to one x value. In the valueSource there might
* exist several datapoints for each x value. These are collected in the list for the
* appropriate datapoint in the dataset.
*
* @throws ChartPlottimeException
*/
public static DefaultMultiValueCategoryDataset createDefaultMultiValueCategoryDataset(ValueSource valueSource, PlotInstance plotInstance) throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultMultiValueCategoryDataset dataset = new DefaultMultiValueCategoryDataset();
DefaultDimensionConfig domainConfig = valueSource.getDomainConfig();
DimensionConfigData domainConfigData = plotInstance.getPlotData().getDimensionConfigData(domainConfig);
// Loop all group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
// the DefaultMultiValueCategoryDataset expects a List of values for each domain value. This map
// maps domain values to lists and is filled while we iterate through all data value below.
Map<Double, List<Double>> valueListsForDomainValues = new HashMap<Double, List<Double>>();
for (Double value : domainConfigData.getDistinctValues()) {
valueListsForDomainValues.put(value, new LinkedList<Double>());
}
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
String seriesName = generateSeriesName(valueSource, groupCellKey, plotInstance.getCurrentPlotConfigurationClone());
Map<PlotDimension, double[]> mainSeriesData = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = mainSeriesData.get(PlotDimension.DOMAIN);
double[] yValues = mainSeriesData.get(PlotDimension.VALUE);
int rowCount = xValues.length;
// Loop all rows and add data into map
double xValue;
double yValue;
String xString;
for (int row = 0; row < rowCount; ++row) {
xValue = xValues[row];
yValue = yValues[row];
valueListsForDomainValues.get(xValue).add(yValue);
}
for (Double value : domainConfigData.getDistinctValues()) {
xString = domainConfigData.getStringForValue(value);
dataset.add(valueListsForDomainValues.get(value), seriesName, xString);
}
}
return dataset;
}
/**
* Same as {@link #createDefaultMultiValueCategoryDataset(ValueSource, PlotConfiguration)}, but
* instead of storing only the values it stores pairs in the lists, where the first value is the
* data value, and the second value holds the index of the value in the series in valueSource.
*
* Must be used for the FormattedScatterRenderer.
*
* @throws ChartPlottimeException
*/
public static DefaultMultiValueCategoryDataset createAnnotatedDefaultMultiValueCategoryDataset(ValueSource valueSource, PlotInstance plotInstance)
throws ChartPlottimeException {
ValueSourceData valueSourceData = plotInstance.getPlotData().getValueSourceData(valueSource);
assertMaxValueCountNotExceededOrThrowException(valueSourceData);
GroupCellSeriesData dataForAllGroupCells = valueSourceData.getSeriesDataForAllGroupCells();
DefaultMultiValueCategoryDataset dataset = new DefaultMultiValueCategoryDataset();
DefaultDimensionConfig domainConfig = valueSource.getDomainConfig();
DimensionConfigData domainConfigData = plotInstance.getPlotData().getDimensionConfigData(domainConfig);
// Loop all group cells and add data to dataset
for (GroupCellKeyAndData groupCellKeyAndData : dataForAllGroupCells) {
// the DefaultMultiValueCategoryDataset expects a List of values for each domain value. This map
// maps domain values to lists and is filled while we iterate through all data value below.
Map<Double, List<Pair<Double, Integer>>> valueListsForDomainValues = new HashMap<Double, List<Pair<Double, Integer>>>();
for (Double value : domainConfigData.getDistinctValues()) {
valueListsForDomainValues.put(value, new LinkedList<Pair<Double, Integer>>());
}
GroupCellKey groupCellKey = groupCellKeyAndData.getKey();
GroupCellData groupCellData = groupCellKeyAndData.getData();
String seriesName = generateSeriesName(valueSource, groupCellKey, plotInstance.getCurrentPlotConfigurationClone());
Map<PlotDimension, double[]> mainSeriesData = groupCellData.getDataForUsageType(SeriesUsageType.MAIN_SERIES);
double[] xValues = mainSeriesData.get(PlotDimension.DOMAIN);
double[] yValues = mainSeriesData.get(PlotDimension.VALUE);
int rowCount = xValues.length;
// Loop all rows and add data into map
double xValue;
double yValue;
String xString;
for (int row = 0; row < rowCount; ++row) {
xValue = xValues[row];
yValue = yValues[row];
Pair<Double, Integer> valueRowNumberPair = new Pair<Double, Integer>(yValue, row);
valueListsForDomainValues.get(xValue).add(valueRowNumberPair);
}
for (Double value : domainConfigData.getDistinctValues()) {
xString = domainConfigData.getStringForValue(value);
dataset.add(valueListsForDomainValues.get(value), seriesName, xString);
}
}
return dataset;
}
private static void assertMaxValueCountNotExceededOrThrowException(ValueSourceData valueSourceData) throws ChartPlottimeException {
if (valueSourceData == null) {
return;
}
int maxAllowedValueCount = PlotConfiguration.getMaxAllowedValueCount();
for (GroupCellKeyAndData groupCellKeyAndData : valueSourceData.getSeriesDataForAllGroupCells()) {
int size = groupCellKeyAndData.getData().getSize();
if (size > maxAllowedValueCount) {
throw new ChartPlottimeException("too_many_values_in_plot", valueSourceData.getValueSource().toString());
}
}
}
}