/**
   * @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;
  }