/**
   * Create a set of datasets each containing the composite function and its constituent parts
   * evaluated over the values
   *
   * @param XValues A dataset containing all the X values to calculate the data at
   * @param DataValues The data that is being fitted too, for visual help.
   * @return an array of datasets
   */
  public DoubleDataset[] display(DoubleDataset XValues, DoubleDataset DataValues) {
    int noOfFunctions = getNoOfFunctions();

    DoubleDataset[] outputs = new DoubleDataset[noOfFunctions + 4];

    outputs[0] = new DoubleDataset(DataValues);

    outputs[1] = makeDataset(XValues);
    outputs[1].setName("Composite function");
    // now add the data
    for (int i = 0; i < XValues.getSize(); i++) {
      double value = val(XValues.get(i));
      outputs[1].set(value, i);
    }

    // now add the errors to the graph, this should provide a good view to
    // how good the fit is quite nicely.
    outputs[2] = new DoubleDataset(XValues);
    outputs[2].setName("Error Value");
    double offset =
        DataValues.min().doubleValue()
            - ((DataValues.max().doubleValue() - DataValues.min().doubleValue()) / 5.0);
    for (int i = 0; i < XValues.getSize(); i++) {
      double value = (val(XValues.get(i)) - DataValues.get(i)) + offset;
      outputs[2].set(value, i);
    }

    outputs[3] = new DoubleDataset(XValues);
    outputs[3].setName("Error Offset");
    // centre for the error
    for (int i = 0; i < XValues.getSize(); i++) {
      double value = offset;
      outputs[3].set(value, i);
    }

    // now add the data for each bit in turn
    int j = 4;
    for (AFunction f : functionList) {
      outputs[j] = f.makeDataset(XValues);
      outputs[j++].setName(f.getName());
    }

    return outputs;
  }
  /**
   * Create a set of datasets each containing the composite function and its constituent parts
   * evaluated over the values
   *
   * @param values datasets containing all the values to evaluate the function at
   * @return an array of datasets
   */
  public DoubleDataset[] display(DoubleDataset... values) {
    if (values == null || values.length == 0) {}

    int noOfFunctions = getNoOfFunctions();

    DoubleDataset[] outputs = new DoubleDataset[noOfFunctions + 1];

    outputs[0] = makeDataset(values);
    outputs[0].setName("Composite function");

    // now add the data for each bit in turn
    int j = 1;
    for (AFunction f : functionList) {
      outputs[j] = f.makeDataset(values);
      outputs[j++].setName(f.getName());
    }

    return outputs;
  }