public ComplexStatsOpImage(
      RenderedImage source,
      int xPeriod,
      int yPeriod,
      ROI roi,
      Range noData,
      boolean useROIAccessor,
      int[] bands,
      StatsType[] statsTypes,
      double[] minBound,
      double[] maxBound,
      int[] numBins) {
    super(
        source,
        xPeriod,
        yPeriod,
        roi,
        noData,
        useROIAccessor,
        bands,
        statsTypes,
        minBound,
        maxBound,
        numBins);

    // Storage of the statistic types indexes if present, and check if they are not simple statistic
    // objects like Mean
    if (statsTypes != null) {
      for (int i = 0; i < statsTypes.length; i++) {
        if (statsTypes[i].getStatsId() < 6) {
          throw new IllegalArgumentException("Wrong statistic types");
        }
      }
    } else {
      throw new IllegalArgumentException("Statistic types not present");
    }

    this.statsTypes = statsTypes;

    // Number of statistics calculated
    this.statNum = statsTypes.length;

    // Storage of the band indexes and length
    this.bands = bands;

    int[] numB = new int[bandsNumber];
    double[] lowValue = new double[bandsNumber];
    double[] highValue = new double[bandsNumber];

    for (int b = 0; b < bandsNumber; b++) {
      numB[b] = numBins.length == 1 ? numBins[0] : numBins[b];
      lowValue[b] = minBound.length == 1 ? minBound[0] : minBound[b];
      highValue[b] = maxBound.length == 1 ? maxBound[0] : maxBound[b];
    }

    // Creation of a global container of all the selected statistics for every band
    this.stats = new Statistics[selectedBands][statNum];
    // Filling of the container
    for (int i = 0; i < selectedBands; i++) {
      for (int j = 0; j < statNum; j++) {
        stats[i][j] =
            StatsFactory.createComplexStatisticsObjectFromInt(
                statsTypes[j].getStatsId(), lowValue[i], highValue[i], numB[i]);
      }
    }
  }