@Override
 public GeneList compute() throws Exception {
   final OperationPool op = OperationPool.getInstance();
   final Collection<Callable<ListView<Gene>>> threadList =
       new ArrayList<Callable<ListView<Gene>>>();
   for (int i = 0; i < geneList.size(); i++) {
     final ListView<Gene> currentGeneList = geneList.get(i);
     Callable<ListView<Gene>> currentThread =
         new Callable<ListView<Gene>>() {
           @Override
           public ListView<Gene> call() throws Exception {
             if (currentGeneList == null) {
               return null;
             }
             ListViewBuilder<Gene> resultLVBuilder = new GeneListViewBuilder();
             for (int j = 0; (j < currentGeneList.size()) && !stopped; j++) {
               Gene currentGene = currentGeneList.get(j);
               Gene geneToAdd = createGeneCopyWithConstantScore(currentGene);
               resultLVBuilder.addElementToBuild(geneToAdd);
             }
             // tell the operation pool that a chromosome is done
             op.notifyDone();
             return resultLVBuilder.getListView();
           }
         };
     threadList.add(currentThread);
   }
   List<ListView<Gene>> result = op.startPool(threadList);
   if (result == null) {
     return null;
   } else {
     return new SimpleGeneList(result, geneList.getGeneScoreType(), geneList.getGeneDBURL());
   }
 }
  @Override
  public long[][] compute() throws Exception {
    long[][] result = new long[geneList1.size()][];
    final OperationPool op = OperationPool.getInstance();
    final Collection<Callable<long[]>> threadList = new ArrayList<Callable<long[]>>();
    for (int i = 0; i < geneList1.size(); i++) {
      final int chromoindex = i;
      Callable<long[]> currentThread =
          new Callable<long[]>() {
            @Override
            public long[] call() throws Exception {
              long[] chromoresult = new long[geneList1.get(chromoindex).size()];
              if ((geneList1 != null) && (geneList2 != null)) {
                chromoresult = handleCases(geneList1.get(chromoindex), geneList2, chromoindex);
              }
              // tell the operation pool that a chromosome is done
              op.notifyDone();
              return chromoresult;
            }
          };
      threadList.add(currentThread);
    }
    if (op.startPool(threadList) == null) {
      return null;
    }

    int i = 0;
    for (long[] currentResult : op.startPool(threadList)) {
      if (currentResult != null) {
        result[i++] = currentResult;
      }
    }
    return result;
  }
  @Override
  public SCWList compute() throws Exception {
    ProjectChromosomes projectChromosomes = ProjectManager.getInstance().getProjectChromosomes();
    final OperationPool op = OperationPool.getInstance();
    final Collection<Callable<Void>> threadList = new ArrayList<Callable<Void>>();
    final SCWListBuilder resultListBuilder = new SCWListBuilder(scwList);

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

            @Override
            public Void call() throws Exception {
              if (currentList != null) {
                // We log each element
                for (int j = 0; (j < currentList.size()) && !stopped; j++) {
                  int start = currentList.get(j).getStart();
                  int stop = currentList.get(j).getStop();
                  float score = currentList.get(j).getScore();
                  // log is define on R+*
                  if (score > 0) {
                    if (logBase == LogBase.BASE_E) {
                      // the Math.log function return the natural log (no needs to change the base)
                      score = (float) Math.log(score);
                    } else {
                      // change of base: logb(x) = logk(x) / logk(b)
                      score = (float) (Math.log(score) / Math.log(logBase.getValue()));
                    }
                  } else if (score < 0) {
                    // can't apply a log function on a negative or null numbers
                    throw new ArithmeticException("Logarithm of a negative value not allowed");
                  }
                  resultListBuilder.addElementToBuild(chromosome, start, stop, score);
                }
              }
              // tell the operation pool that a chromosome is done
              op.notifyDone();
              return null;
            }
          };

      threadList.add(currentThread);
    }
    op.startPool(threadList);
    return resultListBuilder.getSCWList();
  }
  @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();
  }