@Override
  public BinList compute()
      throws InterruptedException, ExecutionException, CloneNotSupportedException {
    final int binSize = binList.getBinSize();
    final int halfWidth = movingWindowWidth / 2 / binSize;
    // we create an array of coefficients. The index correspond to a distance and for each distance
    // we calculate a coefficient
    final double[] weights = new double[halfWidth + 1];
    for (int i = 0; i <= halfWidth; i++) {
      weights[i] = Math.pow(1d - Math.pow(i / (double) halfWidth, 3d), 3d);
    }

    ProjectChromosomes projectChromosomes = ProjectManager.getInstance().getProjectChromosomes();
    final OperationPool op = OperationPool.getInstance();
    final Collection<Callable<Void>> threadList = new ArrayList<Callable<Void>>();
    final BinListBuilder resultListBuilder = new BinListBuilder(binList.getBinSize());

    for (final Chromosome chromosome : projectChromosomes) {
      final ListView<ScoredChromosomeWindow> currentList = binList.get(chromosome);
      Callable<Void> currentThread =
          new Callable<Void>() {

            @Override
            public Void call() throws Exception {
              if (currentList != null) {
                for (int j = 0; (j < currentList.size()) && !stopped; j++) {
                  float score = 0f;
                  if ((currentList.get(j).getScore() != 0) || (fillNullValues)) {
                    // apply the array of coefficients centered on the current value to gauss
                    double sumWts = 0;
                    double sumWtX = 0;
                    double sumWtX2 = 0;
                    double sumWtY = 0;
                    double sumWtXY = 0;
                    for (int k = -halfWidth; (k <= halfWidth) && !stopped; k++) {
                      int movingX = j + k; // x coordinate of the current point in the moving window
                      if ((movingX >= 0) && (movingX < currentList.size())) {
                        int distance = Math.abs(k);
                        if (currentList.get(j + k).getScore() != 0) {
                          sumWts += weights[distance];
                          sumWtX += movingX * weights[distance];
                          sumWtX2 += (movingX ^ 2) * weights[distance];
                          sumWtY += currentList.get(movingX).getScore() * weights[distance];
                          sumWtXY +=
                              movingX * currentList.get(movingX).getScore() * weights[distance];
                        }
                      }
                    }
                    double denom = (sumWts * sumWtX2) - Math.pow(sumWtX, 2);
                    if (denom != 0) {
                      double WLRSlope = ((sumWts * sumWtXY) - (sumWtX * sumWtY)) / denom;
                      double WLRIntercept = ((sumWtX2 * sumWtY) - (sumWtX * sumWtXY)) / denom;
                      double yLoess = (WLRSlope * j) + WLRIntercept;
                      score = (float) yLoess;
                    }
                    resultListBuilder.addElementToBuild(chromosome, score);
                  }
                }
              }
              op.notifyDone();
              return null;
            }
          };
      threadList.add(currentThread);
    }
    op.startPool(threadList);
    return (BinList) resultListBuilder.getSCWList();
  }
 @Override
 public int getStepCount() {
   return binList.getCreationStepCount() + 1;
 }