Commit 575e240c authored by Andrey Filippov's avatar Andrey Filippov
Browse files

speeding up

parent 689efe82
Loading
Loading
Loading
Loading
+144 −82
Original line number Original line Diff line number Diff line
@@ -30,6 +30,8 @@ import ij.ImageStack;


import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;


import javax.swing.SwingUtilities;



public class DebayerScissors {
public class DebayerScissors {
//	showDoubleFloatArrays SDFA_INSTANCE=   new showDoubleFloatArrays();
//	showDoubleFloatArrays SDFA_INSTANCE=   new showDoubleFloatArrays();
@@ -96,7 +98,29 @@ public class DebayerScissors {
  	  final Thread[] threads = newThreadArray(threadsMax);
  	  final Thread[] threads = newThreadArray(threadsMax);
  	  final AtomicInteger ai = new AtomicInteger(0);
  	  final AtomicInteger ai = new AtomicInteger(0);
  	  final int numberOfKernels=tilesY*tilesX;
  	  final int numberOfKernels=tilesY*tilesX;
  	  
	  int indx,dx,dy,tx,ty,li;
	  final int [] nonOverlapSeq = new int[numberOfKernels];
	  int [] nextFirstFindex=new int[4];
	  indx = 0;
	  li=0;
	  
	  for (dy=0;dy<2;dy++) for (dx=0;dx<2;dx++) {
		  for (ty=dy; ty < tilesY; ty+=2) for (tx=dx; tx < tilesX; tx+=2){
			  nonOverlapSeq[indx++] = ty*tilesX + tx;
		  }
		  nextFirstFindex[li++] = indx;
	  }
	  final AtomicInteger aStopIndex = new AtomicInteger(0);
  	  final long startTime = System.nanoTime();
  	  final long startTime = System.nanoTime();
  	  final AtomicInteger tilesFinishedAtomic = new AtomicInteger(1); // first finished will be 1
  	  for (li = 0; li < nextFirstFindex.length; li++){
  		  aStopIndex.set(nextFirstFindex[li]);
  		  if (li>0){
  			  ai.set(nextFirstFindex[li-1]);
  		  }
  		  //		  System.out.println("\n=== nextFirstFindex["+li+"] =" + nextFirstFindex[li]+" === ");

  		  for (int ithread = 0; ithread < threads.length; ithread++) {
  		  for (int ithread = 0; ithread < threads.length; ithread++) {
  			  threads[ithread] = new Thread() {
  			  threads[ithread] = new Thread() {
  				  public void run() {
  				  public void run() {
@@ -114,12 +138,15 @@ public class DebayerScissors {
  							  debayerParameters.debayerRelativeWidthRedblue, // result red/blue mask mpy by scaled default (square)
  							  debayerParameters.debayerRelativeWidthRedblue, // result red/blue mask mpy by scaled default (square)
  							  debayerParameters.debayerRelativeWidthRedblueMain, // green mask when applied to red/blue, main (center)
  							  debayerParameters.debayerRelativeWidthRedblueMain, // green mask when applied to red/blue, main (center)
  							  debayerParameters.debayerRelativeWidthRedblueClones);// green mask when applied to red/blue, clones 
  							  debayerParameters.debayerRelativeWidthRedblueClones);// green mask when applied to red/blue, clones 
  				  
  					  //  					  for (int nTile0 = ai.getAndIncrement(); nTile0 < numberOfKernels; nTile0 = ai.getAndIncrement()) {
  				  for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
  					  for (int nTile0 = ai.getAndIncrement(); nTile0 < aStopIndex.get(); nTile0 = ai.getAndIncrement()) {
  						  int nTile = nonOverlapSeq[nTile0];
  						  tileY = nTile /tilesX;
  						  tileY = nTile /tilesX;
  						  tileX = nTile % tilesX;
  						  tileX = nTile % tilesX;
  					  if (tileX==0) {
  						  if (tileX < 2) {
  						  if (updateStatus) IJ.showStatus("(1)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY);
  							  int trow=(tileY+((tileY & 1)*tilesY))/2;
  							  if (updateStatus) IJ.showStatus("Reducing sampling aliases, row "+(trow+1)+" of "+tilesY);
  							  //  						  System.out.println("(1)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" ("+nTile+"/"+nTile0+") col="+(tileX+1));
  							  if (globalDebugLevel>2) System.out.println("(1)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
  							  if (globalDebugLevel>2) System.out.println("(1)Reducing sampling aliases, row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
  						  }
  						  }


@@ -149,8 +176,8 @@ public class DebayerScissors {
  								  debayerParameters.debayerThreshold, // no high frequencies - use default uniform filter
  								  debayerParameters.debayerThreshold, // no high frequencies - use default uniform filter
  								  debayerParameters.debayerGamma, // power function applied to the amplitudes before generating spectral masks
  								  debayerParameters.debayerGamma, // power function applied to the amplitudes before generating spectral masks
  								  debayerParameters.debayerBonus, // scale far pixels as (1.0+bonus*r/rmax)
  								  debayerParameters.debayerBonus, // scale far pixels as (1.0+bonus*r/rmax)
  							  debayerParameters.mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
  								  debayerParameters.mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
  							  debayerParameters.debayerMaskBlur, // for both masks  sigma for gaussian blur of the binary masks (<0 -do not use "scissors")
  								  debayerParameters.debayerMaskBlur, // for both masks  sigma for Gaussian blur of the binary masks (<0 -do not use "scissors")
  								  debayerParameters.debayerUseScissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_PARAMETERS.debayerRelativeWidthGreen and DEBAYER_PARAMETERS.debayerRelativeWidthRedblue
  								  debayerParameters.debayerUseScissors, // use "scissors", if false - just apply "diamond" ands "square" with DEBAYER_PARAMETERS.debayerRelativeWidthGreen and DEBAYER_PARAMETERS.debayerRelativeWidthRedblue
  								  ((tileY==yTileDebug) && (tileX==xTileDebug))?4:1);
  								  ((tileY==yTileDebug) && (tileX==xTileDebug))?4:1);
  						  //                                               1); // internal debug level ((this.debugLevel>2) && (yTile==yTile0) && (xTile==xTile0))?3:1;
  						  //                                               1); // internal debug level ((this.debugLevel>2) && (yTile==yTile0) && (xTile==xTile0))?3:1;
@@ -167,22 +194,32 @@ public class DebayerScissors {
  							  fht_instance.swapQuadrants(tile[chn]);
  							  fht_instance.swapQuadrants(tile[chn]);
  							  /* accumulate result */
  							  /* accumulate result */
  							  /*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixles, but as the accumulation
  							  /*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixles, but as the accumulation
  						   * takes just small fraction of severtal FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
  							   * takes just small fraction of several FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
  							   */
  							   */


  						  accumulateSquareTile(outPixles[chn], //  float pixels array to accumulate tile
  							  //accumulateSquareTile(
  							  nonSyncAccumulateSquareTile (
  									  outPixles[chn], //  float pixels array to accumulate tile
  									  tile[chn], // data to accumulate to the pixels array
  									  tile[chn], // data to accumulate to the pixels array
  									  imgWidth, // width of pixels array
  									  imgWidth, // width of pixels array
  									  tileX*step, // left corner X
  									  tileX*step, // left corner X
  									  tileY*step); // top corner Y
  									  tileY*step); // top corner Y
  						  }
  						  }
  						  if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "B00");
  						  if ((tileY==yTileDebug) && (tileX==xTileDebug) && (SDFA_instance!=null)) SDFA_instance.showArrays (tile.clone(),debayerParameters.size,debayerParameters.size, "B00");
  					  
     						final int numFinished=tilesFinishedAtomic.getAndIncrement();
       						SwingUtilities.invokeLater(new Runnable() {
       							public void run() {
       								IJ.showProgress(numFinished,numberOfKernels);
       							}
       						});
  					  }
  					  }
  				  }
  				  }
  			  };
  			  };
  		  }		      
  		  }		      
  		  startAndJoin(threads);
  		  startAndJoin(threads);
  	  }
  	  if (updateStatus) IJ.showStatus("Reducing sampling aliases DONE");
  	  IJ.showProgress(1.0);
 // 	  this.debugLevel=wasDebugLevel;
 // 	  this.debugLevel=wasDebugLevel;
  	  /* prepare result stack to return */
  	  /* prepare result stack to return */
  	  ImageStack outStack=new ImageStack(imgWidth,imgHeight);
  	  ImageStack outStack=new ImageStack(imgWidth,imgHeight);
@@ -193,7 +230,7 @@ public class DebayerScissors {
//  	  if (debayerParameters.showEnergy) {
//  	  if (debayerParameters.showEnergy) {
//  		  SDFA_INSTANCE.showArrays (debayerEnergy,tilesX,tilesY, "Debayer-Energy");
//  		  SDFA_INSTANCE.showArrays (debayerEnergy,tilesX,tilesY, "Debayer-Energy");
//  	  }
//  	  }

	  if (globalDebugLevel>0) System.out.println("(1)Reducing sampling aliases done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
  	  return outStack;
  	  return outStack;
    }
    }


@@ -273,6 +310,31 @@ public class DebayerScissors {
   		  }
   		  }
   	  }
   	  }
     }
     }

     void  nonSyncAccumulateSquareTile(
      		  float [] pixels, //  float pixels array to accumulate tile
      		  double []  tile, // data to accumulate to the pixels array
      		  int       width, // width of pixels array
      		  int          x0, // left corner X
      		  int          y0) { // top corner Y
      	  int length=tile.length;
      	  int size=(int) Math.sqrt(length);
      	  int i,j,x,y;
      	  int height=pixels.length/width;
      	  int index=0;
      	  for (i=0;i<size;i++) {
      		  y=y0+i;
      		  if ((y>=0) && (y<height)) {
      			  index=i*size;
      			  for (j=0;j<size;j++) {
      				  x=x0+j;
      				  if ((x>=0) && (x<width)) pixels[y*width+x]+=tile [index];
      				  index++;
      			  }
      		  }
      	  }
        }
     
     synchronized void  accumulateSquareTile(
     synchronized void  accumulateSquareTile(
   		  double [] pixels, //  float pixels array to accumulate tile
   		  double [] pixels, //  float pixels array to accumulate tile
   		  double []  tile, // data to accumulate to the pixels array
   		  double []  tile, // data to accumulate to the pixels array
+154 −81
Original line number Original line Diff line number Diff line
@@ -39,6 +39,8 @@ import ij.process.ImageProcessor;
import java.io.IOException;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;


import javax.swing.SwingUtilities;

import loci.common.services.DependencyException;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceException;
import loci.formats.FormatException;
import loci.formats.FormatException;
@@ -473,7 +475,7 @@ public class EyesisCorrections {
						this.defectsDiff[srcChannel]=this.pixelMapping.getDefectsDiff(srcChannel);
						this.defectsDiff[srcChannel]=this.pixelMapping.getDefectsDiff(srcChannel);
						if (this.debugLevel>0){
						if (this.debugLevel>0){
							if (this.defectsXY[srcChannel]==null){
							if (this.defectsXY[srcChannel]==null){
								System.out.println("No pixel defects info is availabele for channel "+srcChannel);
								System.out.println("No pixel defects info is available for channel "+srcChannel);
							} else {
							} else {
								System.out.println("Extracted "+this.defectsXY[srcChannel].length+" pixel outlayers for channel "+srcChannel+
								System.out.println("Extracted "+this.defectsXY[srcChannel].length+" pixel outlayers for channel "+srcChannel+
										" (x:y:difference");
										" (x:y:difference");
@@ -1712,14 +1714,31 @@ public class EyesisCorrections {
		  final AtomicInteger ai = new AtomicInteger(0);
		  final AtomicInteger ai = new AtomicInteger(0);
		  final int numberOfKernels=     tilesY*tilesX*nChn;
		  final int numberOfKernels=     tilesY*tilesX*nChn;
		  final int numberOfKernelsInChn=tilesY*tilesX;
		  final int numberOfKernelsInChn=tilesY*tilesX;
//		  if (globalDebugLevel>1) 
		  
			  System.out.println("Eyesis_Correction:convolveStackWithKernelStack :\n"+
		  int ichn,indx,dx,dy,tx,ty,li;
		  final int [] nonOverlapSeq = new int[numberOfKernels];
		  int [] nextFirstFindex=new int[16*nChn];
		  indx = 0;
		  li=0;
		  for (ichn=0;ichn<nChn;ichn++) for (dy=0;dy<4;dy++) for (dx=0;dx<4;dx++) {
			  for (ty=dy; ty < tilesY; ty+=4) for (tx=dx; tx < tilesX; tx+=4){
				  nonOverlapSeq[indx++] = ichn*numberOfKernelsInChn+ ty*tilesX + tx;
			  }
			  nextFirstFindex[li++] = indx;
		  }
		  final AtomicInteger aStopIndex = new AtomicInteger(0);
		  final AtomicInteger tilesFinishedAtomic = new AtomicInteger(1); // first finished will be 1
		  
		  if (globalDebugLevel>1) 
			  System.out.println("Eyesis_Corrections:convolveStackWithKernelStack :\n"+
				  "globalDebugLevel="+globalDebugLevel+"\n"+
				  "globalDebugLevel="+globalDebugLevel+"\n"+
				  "imgWidth="+imgWidth+"\n"+
				  "imgWidth="+imgWidth+"\n"+
				  "imgHeight="+imgHeight+"\n"+
				  "imgHeight="+imgHeight+"\n"+
				  "tilesX="+tilesX+"\n"+
				  "tilesX="+tilesX+"\n"+
				  "tilesY="+tilesY+"\n"+
				  "tilesY="+tilesY+"\n"+
				  "nChn="+nChn+"\n"+
				  "step="+step+"\n"+
				  "step="+step+"\n"+
				  "size="+size+"\n"+
				  "kernelSize="+kernelSize+"\n"+
				  "kernelSize="+kernelSize+"\n"+
				  "kernelWidth="+kernelWidth+"\n"+
				  "kernelWidth="+kernelWidth+"\n"+
				  "kernelNumHor="+kernelNumHor+"\n"+
				  "kernelNumHor="+kernelNumHor+"\n"+
@@ -1727,6 +1746,12 @@ public class EyesisCorrections {
		  
		  
		  
		  
		  final long startTime = System.nanoTime();
		  final long startTime = System.nanoTime();
		  for (li = 0; li < nextFirstFindex.length; li++){
			  aStopIndex.set(nextFirstFindex[li]);
			  if (li>0){
				  ai.set(nextFirstFindex[li-1]);
			  }
//			  System.out.println("\n=== nextFirstFindex["+li+"] =" + nextFirstFindex[li]+" === ");
			  for (int ithread = 0; ithread < threads.length; ithread++) {
			  for (int ithread = 0; ithread < threads.length; ithread++) {
				  threads[ithread] = new Thread() {
				  threads[ithread] = new Thread() {
					  public void run() {
					  public void run() {
@@ -1741,12 +1766,16 @@ public class EyesisCorrections {
						  //					  double debug_sum;
						  //					  double debug_sum;
						  //					  int i;
						  //					  int i;
						  DoubleFHT fht_instance =new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null)
						  DoubleFHT fht_instance =new DoubleFHT(); // provide DoubleFHT instance to save on initializations (or null)
					  for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
						  //					  for (int nTile0 = ai.getAndIncrement(); nTile0 < numberOfKernels; nTile0 = ai.getAndIncrement()) {
						  for (int nTile0 = ai.getAndIncrement(); nTile0 < aStopIndex.get(); nTile0 = ai.getAndIncrement()) {
							  //aStopIndex
							  int nTile = nonOverlapSeq[nTile0];
							  chn=nTile/numberOfKernelsInChn;
							  chn=nTile/numberOfKernelsInChn;
							  tileY =(nTile % numberOfKernelsInChn)/tilesX;
							  tileY =(nTile % numberOfKernelsInChn)/tilesX;
							  tileX = nTile % tilesX;
							  tileX = nTile % tilesX;
						  if (tileX==0) {
							  if (tileX < 4) {
							  if (updateStatus) IJ.showStatus("Convolving image with kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+tilesY);
	  							  int trow=(tileY+ ((tileY & 3) * tilesY))/4;
								  if (updateStatus) IJ.showStatus("Convolving image with kernels, channel "+(chn+1)+" of "+nChn+", row "+(trow+1)+" of "+tilesY);
								  if (globalDebugLevel>2) System.out.println("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
								  if (globalDebugLevel>2) System.out.println("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+tilesY+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
							  }
							  }


@@ -1793,25 +1822,43 @@ public class EyesisCorrections {
							  /* accumulate result */
							  /* accumulate result */
							  //if ((tileY==tilesY/2) && (tileX==tilesX/2))  SDFA_INSTANCE.showArrays(outTile,size,size, "out-"+chn);
							  //if ((tileY==tilesY/2) && (tileX==tilesX/2))  SDFA_INSTANCE.showArrays(outTile,size,size, "out-"+chn);
							  /*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixels, but as the accumulation
							  /*This is synchronized method. It is possible to make threads to write to non-overlapping regions of the outPixels, but as the accumulation
						   * takes just small fraction of severtal FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
							   * takes just small fraction of several FHTs, it should be OK - reasonable number of threads will spread and not "stay in line"
							   */
							   */
						  accumulateSquareTile(outPixels[chn], //  float pixels array to accumulate tile

							  // Add smart synchronization - wait only if is too far ahead. First test - no synchronization at all

							  //accumulateSquareTile(
//							  System.out.print(tileY+":"+tileX+"/"+chn+"("+nTile0+"/"+nTile+") ");
//							  if (tileX < 4)System.out.println();
							  nonSyncAccumulateSquareTile(
									  outPixels[chn], //  float pixels array to accumulate tile
									  outTile, // data to accumulate to the pixels array
									  outTile, // data to accumulate to the pixels array
									  imgWidth, // width of pixels array
									  imgWidth, // width of pixels array
									  (tileX-1)*step, // left corner X
									  (tileX-1)*step, // left corner X
									  (tileY-1)*step); // top corner Y
									  (tileY-1)*step); // top corner Y
							  final int numFinished=tilesFinishedAtomic.getAndIncrement();
							  SwingUtilities.invokeLater(new Runnable() {
								  public void run() {
									  IJ.showProgress(numFinished,numberOfKernels);
								  }
							  });
							  
							  //numberOfKernels
						  }
						  }
					  }
					  }
				  };
				  };
			  }		      
			  }		      
			  startAndJoin(threads);
			  startAndJoin(threads);
		  if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
		  }

		  if (updateStatus) IJ.showStatus("Convolution DONE");
		  if (globalDebugLevel > 1) System.out.println("Threads done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
		  IJ.showProgress(1.0);
		  /* prepare result stack to return */
		  /* prepare result stack to return */
		  ImageStack outStack=new ImageStack(imgWidth,imgHeight);
		  ImageStack outStack=new ImageStack(imgWidth,imgHeight);
		  for (i=0;i<nChn;i++) {
		  for (i=0;i<nChn;i++) {
			  outStack.addSlice(imageStack.getSliceLabel(i+1), outPixels[i]);
			  outStack.addSlice(imageStack.getSliceLabel(i+1), outPixels[i]);
		  }
		  }
		  if (globalDebugLevel > 0) System.out.println("Convolution done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
		  return outStack;
		  return outStack;
	  }
	  }
	  /* Adds zero pixels around the image, "extending canvas" */
	  /* Adds zero pixels around the image, "extending canvas" */
@@ -1942,6 +1989,32 @@ public class EyesisCorrections {
	   		  }
	   		  }
	   	  }
	   	  }
	     }
	     }

	     void  nonSyncAccumulateSquareTile(
		   		  float [] pixels, //  float pixels array to accumulate tile
		   		  double []  tile, // data to accumulate to the pixels array
		   		  int       width, // width of pixels array
		   		  int          x0, // left corner X
		   		  int          y0) { // top corner Y
		   	  int length=tile.length;
		   	  int size=(int) Math.sqrt(length);
		   	  int i,j,x,y;
		   	  int height=pixels.length/width;
		   	  int index=0;
		   	  for (i=0;i<size;i++) {
		   		  y=y0+i;
		   		  if ((y>=0) && (y<height)) {
		   			  index=i*size;
		   			  for (j=0;j<size;j++) {
		   				  x=x0+j;
		   				  if ((x>=0) && (x<width)) pixels[y*width+x]+=tile [index];
		   				  index++;
		   			  }
		   		  }
		   	  }
		     }
	     
	     
	     synchronized void  accumulateSquareTile(
	     synchronized void  accumulateSquareTile(
	   		  double [] pixels, //  float pixels array to accumulate tile
	   		  double [] pixels, //  float pixels array to accumulate tile
	   		  double []  tile, // data to accumulate to the pixels array
	   		  double []  tile, // data to accumulate to the pixels array
+1 −1
Original line number Original line Diff line number Diff line
@@ -3967,7 +3967,7 @@ private Panel panel1,panel2,panel3,panel4,panel5,panel5a, panel6,panel7,panelPos
	  final AtomicInteger ai = new AtomicInteger(0);
	  final AtomicInteger ai = new AtomicInteger(0);
	  final int numberOfKernels=     tilesY*tilesX*nChn;
	  final int numberOfKernels=     tilesY*tilesX*nChn;
	  final int numberOfKernelsInChn=tilesY*tilesX;
	  final int numberOfKernelsInChn=tilesY*tilesX;
//	  if (MASTER_DEBUG_LEVEL>1) 
	  if (MASTER_DEBUG_LEVEL>1) 
		  System.out.println("Eyesis_Correction:convolveStackWithKernelStack :\n"+
		  System.out.println("Eyesis_Correction:convolveStackWithKernelStack :\n"+
			  "MASTER_DEBUG_LEVEL="+MASTER_DEBUG_LEVEL+"\n"+
			  "MASTER_DEBUG_LEVEL="+MASTER_DEBUG_LEVEL+"\n"+
			  "imgWidth="+imgWidth+"\n"+
			  "imgWidth="+imgWidth+"\n"+
+765 −758
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ import java.util.HashSet;


	/* returns 2 masks (0:0 in the top left corner, match fht) [0] - for greens, [1] - for red/blue */
	/* returns 2 masks (0:0 in the top left corner, match fht) [0] - for greens, [1] - for red/blue */
	/* Possible improvements: - 1 make the initial green mask (or actually "fan"-like image) to have sharper ends.
	/* Possible improvements: - 1 make the initial green mask (or actually "fan"-like image) to have sharper ends.
                             2. detect periodic (line of spots) on the spectrum aplitudes (corresponds to thin lines) and use this
                             2. detect periodic (line of spots) on the spectrum amplitudes (corresponds to thin lines) and use this
                                info to confirm this area to belong to the main spectrum */
                                info to confirm this area to belong to the main spectrum */


	public double [][] aliasScissors(double [] green_fht, // fht array for green, will be masked in-place
	public double [][] aliasScissors(double [] green_fht, // fht array for green, will be masked in-place
@@ -115,13 +115,14 @@ import java.util.HashSet;
			}
			}


			/* Maybe here we need to unmasked (wide bandwidth) green_amp? */
			/* Maybe here we need to unmasked (wide bandwidth) green_amp? */
        red_blue_mask= calcRedBlueAliasMaskRays (green_amp, // both halves are needed ??
			red_blue_mask= calcRedBlueAliasMaskRays (
					green_amp, // both halves are needed ??
					green_mask_for_redblue_main, // may be null if amp_pixels is already masked
					green_mask_for_redblue_main, // may be null if amp_pixels is already masked
					green_mask_for_redblue_clones,
					green_mask_for_redblue_clones,
					pol_instace, // initialized instance (if null - skip rays processing)
					pol_instace, // initialized instance (if null - skip rays processing)
                                               mainToAlias,// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
					mainToAlias,// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
					debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax)
					debayer_bonus, // scale far pixels as (1.0+bonus*r/rmax)
                                               this_debug);// relative main/alias amplitudes to enable lixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)
					this_debug);// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out)


			/* add    double mainToAlias){// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) */
			/* add    double mainToAlias){// relative main/alias amplitudes to enable pixels (i.e. 0.5 means that if alias is >0.5*main, the pixel will be masked out) */


@@ -134,7 +135,7 @@ import java.util.HashSet;
		} else { // debayer_mask_blur<0 : use default masks
		} else { // debayer_mask_blur<0 : use default masks
			green_mask=lopass[1][0].clone(); //green_lopass.clone(); variable (wide) filter here)
			green_mask=lopass[1][0].clone(); //green_lopass.clone(); variable (wide) filter here)
			red_blue_mask=lopass[1][1].clone(); //red_blue_lopass.clone();
			red_blue_mask=lopass[1][1].clone(); //red_blue_lopass.clone();
       if (!useFancyDebayer) for (i=0;i<green_mask.length;i++) { // no high-frequency componnets detected - reduce noise by extra (narrow) filtering
			if (!useFancyDebayer) for (i=0;i<green_mask.length;i++) { // no high-frequency componets detected - reduce noise by extra (narrow) filtering
				green_mask[i]*=   lopass[0][0][i]; // *=   green_lopass[i];
				green_mask[i]*=   lopass[0][0][i]; // *=   green_lopass[i];
				red_blue_mask[i]*=lopass[0][1][i]; // *=red_blue_lopass[i];
				red_blue_mask[i]*=lopass[0][1][i]; // *=red_blue_lopass[i];
			}
			}
@@ -158,7 +159,8 @@ import java.util.HashSet;
		return result;
		return result;
	}
	}


  public double [] calcRedBlueAliasMaskRays (double [] green_amp, // both halves are needed ??
	public double [] calcRedBlueAliasMaskRays (
			double [] green_amp, // both halves are needed ??
			double [] green_mask, // may be null if amp_pixels is already masked
			double [] green_mask, // may be null if amp_pixels is already masked
			double [] green_mask_clones, // mask (more inclusive than just green_mask) to be used with clones
			double [] green_mask_clones, // mask (more inclusive than just green_mask) to be used with clones
			PolarSpectrums pol_instace, // initialized instance (if null - skip rays processing)
			PolarSpectrums pol_instace, // initialized instance (if null - skip rays processing)
@@ -181,15 +183,12 @@ import java.util.HashSet;
		/* Combine into mask by comparing pixels[] from the zero and 7 aliases */
		/* Combine into mask by comparing pixels[] from the zero and 7 aliases */
		double d;
		double d;
		int nAlias;
		int nAlias;
    int [][] aliasMapRedBlue={{-2,-2},{-2,-1},{-2,0},{-2,1},
		int [][] aliasMapRedBlue={
				{-2,-2},{-2,-1},{-2,0},{-2,1},
				{-1,-2},{-1,-1},{-1,0},{-1,1},
				{-1,-2},{-1,-1},{-1,0},{-1,1},
				{ 0,-2},{ 0,-1},       { 0,1},
				{ 0,-2},{ 0,-1},       { 0,1},
				{ 1,-2},{ 1,-1},{ 1,0},{ 1,1}};
				{ 1,-2},{ 1,-1},{ 1,0},{ 1,1}};


/*    int [][] aliasMap={{-1,-1},{-1,0},{-1,1},
                       { 0,-1},       { 0,1},
                       { 1,-1},{ 1,0},{ 1,1}};*/

		/* First step - mask out all the pixels where at least one of the alias amplitude is above the main one */
		/* First step - mask out all the pixels where at least one of the alias amplitude is above the main one */
		if (this_debug>2) SDFA_instance.showArrays(amp.clone(),  "amp");
		if (this_debug>2) SDFA_instance.showArrays(amp.clone(),  "amp");
		if (this_debug>2) SDFA_instance.showArrays(amp_clones,  "amp_clones");
		if (this_debug>2) SDFA_instance.showArrays(amp_clones,  "amp_clones");
@@ -205,6 +204,13 @@ import java.util.HashSet;
				for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
				for(nAlias=0;nAlias<aliasMapRedBlue.length; nAlias++) {
					y=(i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size;
					y=(i-aliasX*aliasMapRedBlue[nAlias][0]+size) % size;
					x=(j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size;
					x=(j-aliasX*aliasMapRedBlue[nAlias][1]+size) % size;
					/*
					if (amp_clones[(y>hsize)? ((size-y)*size+((size-x)%size)):y*size+x]>d) {
						mask[index]=-1.0;
						mask[index_back]=-1.0;
						break;
					}
					*/
					if (y>hsize) {
					if (y>hsize) {
						y=size-y;
						y=size-y;
						x=(size-x)%size;
						x=(size-x)%size;
@@ -214,6 +220,7 @@ import java.util.HashSet;
						mask[index_back]=-1.0;
						mask[index_back]=-1.0;
						break;
						break;
					}
					}
					
				}
				}
			}
			}
		}
		}