Program: 11403
Project: 11403
Buggy source:
/** 
 * Compute final cluster centers for all clusters using K-mean clustering method
 * @param srcBandList    the input bands
 * @param tileRectangles Array of rectangles for all source tiles of the image
 * @param op             the operator
 */
private void computeFinalTerrainClusterCenters(final double[][] fdd,final java.util.List<ClusterInfo> pvCenterList,final java.util.List<ClusterInfo> pdCenterList,final java.util.List<ClusterInfo> psCenterList,final PolBandUtils.PolSourceBand srcBandList,final Rectangle[] tileRectangles,final PolarimetricClassificationOp op){
  boolean endIteration=false;
  final StatusProgressMonitor status=new StatusProgressMonitor(StatusProgressMonitor.TYPE.SUBTASK);
  status.beginTask("String_Node_Str",tileRectangles.length * maxIterations);
  final int pvNumClusters=pvCenterList.size();
  final int pdNumClusters=pdCenterList.size();
  final int psNumClusters=psCenterList.size();
  final int maxNumClusters=Math.max(pvNumClusters,Math.max(pdNumClusters,psNumClusters));
  final int[][] clusterCounter=new int[3][maxNumClusters];
  final ThreadManager threadManager=new ThreadManager();
  try {
    for (int it=0; (it < maxIterations && !endIteration); ++it) {
      final double[][][] pvSumRe=new double[pvNumClusters][3][3];
      final double[][][] pvSumIm=new double[pvNumClusters][3][3];
      final double[][][] pdSumRe=new double[pdNumClusters][3][3];
      final double[][][] pdSumIm=new double[pdNumClusters][3][3];
      final double[][][] psSumRe=new double[psNumClusters][3][3];
      final double[][][] psSumIm=new double[psNumClusters][3][3];
      java.util.Arrays.fill(clusterCounter[0],0);
      java.util.Arrays.fill(clusterCounter[1],0);
      java.util.Arrays.fill(clusterCounter[2],0);
      for (      final Rectangle rectangle : tileRectangles) {
        final Thread worker=new Thread(){
          final Tile[] sourceTiles=new Tile[srcBandList.srcBands.length];
          final ProductData[] dataBuffers=new ProductData[srcBandList.srcBands.length];
          final double[][] Tr=new double[3][3];
          final double[][] Ti=new double[3][3];
          @Override public void run(){
            op.checkIfCancelled();
            final int x0=rectangle.x;
            final int y0=rectangle.y;
            final int w=rectangle.width;
            final int h=rectangle.height;
            final int xMax=x0 + w;
            final int yMax=y0 + h;
            final Rectangle sourceRectangle=getSourceRectangle(x0,y0,w,h);
            for (int i=0; i < sourceTiles.length; ++i) {
              sourceTiles[i]=op.getSourceTile(srcBandList.srcBands[i],sourceRectangle);
              dataBuffers[i]=sourceTiles[i].getDataBuffer();
            }
            final TileIndex srcIndex=new TileIndex(sourceTiles[0]);
            for (int y=y0; y < yMax; ++y) {
              for (int x=x0; x < xMax; ++x) {
                PolOpUtils.getMeanCoherencyMatrix(x,y,halfWindowSizeX,halfWindowSizeY,srcWidth,srcHeight,sourceProductType,srcIndex,dataBuffers,Tr,Ti);
                int clusterIdx;
synchronized (clusterCounter) {
                  if (mask[y][x] < -64) {
                    clusterIdx=findClosestCluster(Tr,Ti,pvCenterList);
                    computeSummationOfT3(clusterIdx + 1,Tr,Ti,pvSumRe,pvSumIm);
                    clusterCounter[0][clusterIdx]+=1;
                    mask[y][x]=(byte)(-128 + clusterIdx);
                  }
 else                   if (mask[y][x] < 0) {
                    clusterIdx=findClosestCluster(Tr,Ti,pdCenterList);
                    computeSummationOfT3(clusterIdx + 1,Tr,Ti,pdSumRe,pdSumIm);
                    clusterCounter[1][clusterIdx]+=1;
                    mask[y][x]=(byte)(-64 + clusterIdx);
                  }
 else                   if (mask[y][x] < 64) {
                    clusterIdx=findClosestCluster(Tr,Ti,psCenterList);
                    computeSummationOfT3(clusterIdx + 1,Tr,Ti,psSumRe,psSumIm);
                    clusterCounter[2][clusterIdx]+=1;
                    mask[y][x]=(byte)clusterIdx;
                  }
 else {
                    java.util.List<ClusterInfo> allCenterList=new ArrayList<>();
                    allCenterList.addAll(pvCenterList);
                    allCenterList.addAll(pdCenterList);
                    allCenterList.addAll(psCenterList);
                    clusterIdx=findClosestCluster(Tr,Ti,allCenterList);
                    if (clusterIdx >= pvNumClusters + pdNumClusters) {
                      clusterIdx-=pvNumClusters + pdNumClusters;
                      computeSummationOfT3(clusterIdx + 1,Tr,Ti,psSumRe,psSumIm);
                      clusterCounter[2][clusterIdx]+=1;
                      mask[y][x]=(byte)clusterIdx;
                    }
 else                     if (clusterIdx >= pvNumClusters) {
                      clusterIdx-=pvNumClusters;
                      computeSummationOfT3(clusterIdx + 1,Tr,Ti,pdSumRe,pdSumIm);
                      clusterCounter[1][clusterIdx]+=1;
                      mask[y][x]=(byte)(-64 + clusterIdx);
                    }
 else {
                      computeSummationOfT3(clusterIdx + 1,Tr,Ti,pvSumRe,pvSumIm);
                      clusterCounter[0][clusterIdx]+=1;
                      mask[y][x]=(byte)(-128 + clusterIdx);
                    }
                  }
                }
              }
            }
          }
        }
;
        threadManager.add(worker);
        status.worked(1);
      }
      threadManager.finish();
      updateClusterCenter(pvCenterList,clusterCounter[0],pvSumRe,pvSumIm);
      updateClusterCenter(pdCenterList,clusterCounter[1],pdSumRe,pdSumIm);
      updateClusterCenter(psCenterList,clusterCounter[2],psSumRe,psSumIm);
    }
    final double[] pvAvgClusterPower=new double[pvNumClusters];
    final double[] pdAvgClusterPower=new double[pdNumClusters];
    final double[] psAvgClusterPower=new double[psNumClusters];
    int clusterIdx=-1;
    for (int y=0; y < srcHeight; y++) {
      for (int x=0; x < srcWidth; x++) {
        if (mask[y][x] < -64) {
          clusterIdx=mask[y][x] + 128;
          pvAvgClusterPower[clusterIdx]+=fdd[y][x];
        }
 else         if (mask[y][x] < 0) {
          clusterIdx=mask[y][x] + 64;
          pdAvgClusterPower[clusterIdx]+=fdd[y][x];
        }
 else {
          clusterIdx=mask[y][x];
          psAvgClusterPower[clusterIdx]+=fdd[y][x];
        }
      }
    }
    for (int c=0; c < pvNumClusters; c++) {
      pvAvgClusterPower[c]/=clusterCounter[0][c];
    }
    for (int c=0; c < pdNumClusters; c++) {
      pdAvgClusterPower[c]/=clusterCounter[1][c];
    }
    for (int c=0; c < psNumClusters; c++) {
      psAvgClusterPower[c]/=clusterCounter[2][c];
    }
    pvColourIndexMap=new int[pvNumClusters];
    pdColourIndexMap=new int[pdNumClusters];
    psColourIndexMap=new int[psNumClusters];
    for (int c=0; c < pvNumClusters; c++) {
      pvColourIndexMap[c]=numInitialClusters + getColourIndex(c,pvAvgClusterPower,numInitialClusters) + 1;
    }
    for (int c=0; c < pdNumClusters; c++) {
      pdColourIndexMap[c]=2 * numInitialClusters + getColourIndex(c,pdAvgClusterPower,numInitialClusters) + 1;
    }
    for (int c=0; c < psNumClusters; c++) {
      psColourIndexMap[c]=getColourIndex(c,psAvgClusterPower,numInitialClusters) + 1;
    }
  }
 catch (  Throwable e) {
    OperatorUtils.catchOperatorException(op.getId() + "String_Node_Str",e);
  }
 finally {
    status.done();
  }
}

Fixed version (ground truth):
/** 
 * Compute final cluster centers for all clusters using K-mean clustering method
 * @param srcBandList    the input bands
 * @param tileRectangles Array of rectangles for all source tiles of the image
 * @param op             the operator
 */
private void computeFinalTerrainClusterCenters(final double[][] fdd,final java.util.List<ClusterInfo> pvCenterList,final java.util.List<ClusterInfo> pdCenterList,final java.util.List<ClusterInfo> psCenterList,final PolBandUtils.PolSourceBand srcBandList,final Rectangle[] tileRectangles,final PolarimetricClassificationOp op){
  boolean endIteration=false;
  final StatusProgressMonitor status=new StatusProgressMonitor(StatusProgressMonitor.TYPE.SUBTASK);
  status.beginTask("String_Node_Str",tileRectangles.length * maxIterations);
  final int pvNumClusters=pvCenterList.size();
  final int pdNumClusters=pdCenterList.size();
  final int psNumClusters=psCenterList.size();
  final int maxNumClusters=Math.max(pvNumClusters,Math.max(pdNumClusters,psNumClusters));
  final int[][] clusterCounter=new int[3][maxNumClusters];
  final ThreadManager threadManager=new ThreadManager();
  try {
    for (int it=0; (it < maxIterations && !endIteration); ++it) {
      final double[][][] pvSumRe=new double[pvNumClusters][3][3];
      final double[][][] pvSumIm=new double[pvNumClusters][3][3];
      final double[][][] pdSumRe=new double[pdNumClusters][3][3];
      final double[][][] pdSumIm=new double[pdNumClusters][3][3];
      final double[][][] psSumRe=new double[psNumClusters][3][3];
      final double[][][] psSumIm=new double[psNumClusters][3][3];
      java.util.Arrays.fill(clusterCounter[0],0);
      java.util.Arrays.fill(clusterCounter[1],0);
      java.util.Arrays.fill(clusterCounter[2],0);
      for (      final Rectangle rectangle : tileRectangles) {
        final Thread worker=new Thread(){
          final Tile[] sourceTiles=new Tile[srcBandList.srcBands.length];
          final ProductData[] dataBuffers=new ProductData[srcBandList.srcBands.length];
          final double[][] Tr=new double[3][3];
          final double[][] Ti=new double[3][3];
          @Override public void run(){
            op.checkIfCancelled();
            final int x0=rectangle.x;
            final int y0=rectangle.y;
            final int w=rectangle.width;
            final int h=rectangle.height;
            final int xMax=x0 + w;
            final int yMax=y0 + h;
            final Rectangle sourceRectangle=getSourceRectangle(x0,y0,w,h);
            for (int i=0; i < sourceTiles.length; ++i) {
              sourceTiles[i]=op.getSourceTile(srcBandList.srcBands[i],sourceRectangle);
              dataBuffers[i]=sourceTiles[i].getDataBuffer();
            }
            final TileIndex srcIndex=new TileIndex(sourceTiles[0]);
            for (int y=y0; y < yMax; ++y) {
              for (int x=x0; x < xMax; ++x) {
                PolOpUtils.getMeanCoherencyMatrix(x,y,halfWindowSizeX,halfWindowSizeY,srcWidth,srcHeight,sourceProductType,srcIndex,dataBuffers,Tr,Ti);
synchronized (clusterCounter) {
                  if (category[y][x] == Categories.vol) {
                    cluster[y][x]=findClosestCluster(Tr,Ti,pvCenterList);
                    computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,pvSumRe,pvSumIm);
                    clusterCounter[0][cluster[y][x]]+=1;
                  }
 else                   if (category[y][x] == Categories.dbl) {
                    cluster[y][x]=findClosestCluster(Tr,Ti,pdCenterList);
                    computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,pdSumRe,pdSumIm);
                    clusterCounter[1][cluster[y][x]]+=1;
                  }
 else                   if (category[y][x] == Categories.suf) {
                    cluster[y][x]=findClosestCluster(Tr,Ti,psCenterList);
                    computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,psSumRe,psSumIm);
                    clusterCounter[2][cluster[y][x]]+=1;
                  }
 else {
                    final int nearestPvCluster=findClosestCluster(Tr,Ti,pvCenterList);
                    final int nearestPdCluster=findClosestCluster(Tr,Ti,pdCenterList);
                    final int nearestPsCluster=findClosestCluster(Tr,Ti,psCenterList);
                    final double dPv=HAlphaWishart.computeWishartDistance(Tr,Ti,pvCenterList.get(nearestPvCluster));
                    final double dPd=HAlphaWishart.computeWishartDistance(Tr,Ti,pdCenterList.get(nearestPdCluster));
                    final double dPs=HAlphaWishart.computeWishartDistance(Tr,Ti,psCenterList.get(nearestPsCluster));
                    if (dPv <= dPd && dPv <= dPs) {
                      cluster[y][x]=nearestPvCluster;
                      computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,pvSumRe,pvSumIm);
                      clusterCounter[0][cluster[y][x]]+=1;
                      category[y][x]=Categories.vol;
                    }
 else                     if (dPd <= dPv && dPd <= dPs) {
                      cluster[y][x]=nearestPdCluster;
                      computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,pdSumRe,pdSumIm);
                      clusterCounter[1][cluster[y][x]]+=1;
                      category[y][x]=Categories.dbl;
                    }
 else {
                      cluster[y][x]=nearestPsCluster;
                      computeSummationOfT3(cluster[y][x] + 1,Tr,Ti,psSumRe,psSumIm);
                      clusterCounter[2][cluster[y][x]]+=1;
                      category[y][x]=Categories.suf;
                    }
                  }
                }
              }
            }
          }
        }
;
        threadManager.add(worker);
        status.worked(1);
      }
      threadManager.finish();
      updateClusterCenter(pvCenterList,clusterCounter[0],pvSumRe,pvSumIm);
      updateClusterCenter(pdCenterList,clusterCounter[1],pdSumRe,pdSumIm);
      updateClusterCenter(psCenterList,clusterCounter[2],psSumRe,psSumIm);
    }
    final double[] pvAvgClusterPower=new double[pvNumClusters];
    final double[] pdAvgClusterPower=new double[pdNumClusters];
    final double[] psAvgClusterPower=new double[psNumClusters];
    for (int y=0; y < srcHeight; y++) {
      for (int x=0; x < srcWidth; x++) {
        if (category[y][x] == Categories.vol) {
          pvAvgClusterPower[cluster[y][x]]+=fdd[y][x];
        }
 else         if (category[y][x] == Categories.dbl) {
          pdAvgClusterPower[cluster[y][x]]+=fdd[y][x];
        }
 else {
          psAvgClusterPower[cluster[y][x]]+=fdd[y][x];
        }
      }
    }
    for (int c=0; c < pvNumClusters; c++) {
      pvAvgClusterPower[c]/=clusterCounter[0][c];
    }
    for (int c=0; c < pdNumClusters; c++) {
      pdAvgClusterPower[c]/=clusterCounter[1][c];
    }
    for (int c=0; c < psNumClusters; c++) {
      psAvgClusterPower[c]/=clusterCounter[2][c];
    }
    pvColourIndexMap=new int[pvNumClusters];
    pdColourIndexMap=new int[pdNumClusters];
    psColourIndexMap=new int[psNumClusters];
    for (int c=0; c < pvNumClusters; c++) {
      pvColourIndexMap[c]=numInitialClusters + getColourIndex(c,pvAvgClusterPower,numInitialClusters) + 1;
    }
    for (int c=0; c < pdNumClusters; c++) {
      pdColourIndexMap[c]=2 * numInitialClusters + getColourIndex(c,pdAvgClusterPower,numInitialClusters) + 1;
    }
    for (int c=0; c < psNumClusters; c++) {
      psColourIndexMap[c]=getColourIndex(c,psAvgClusterPower,numInitialClusters) + 1;
    }
  }
 catch (  Throwable e) {
    OperatorUtils.catchOperatorException(op.getId() + "String_Node_Str",e);
  }
 finally {
    status.done();
  }
}