/**
  * Execute plugin functionality: stack FFT with window function, max projection over all slices
  * (phase, Z angle), blank out central 1/8 circle (set to min value), display min-max.
  */
 public ResultSet exec(ImagePlus... imps) {
   ImagePlus imp = imps[0];
   Util_StackFFT2D stackFFT2D = new Util_StackFFT2D();
   stackFFT2D.resultTypeChoice = Util_StackFFT2D.resultType[1];
   ImagePlus impF = stackFFT2D.exec(imp);
   IJ.run(impF, "Z Project...", "projection=[Max Intensity]");
   ImagePlus impProjF = ij.WindowManager.getCurrentImage();
   maskCentralRegion(impProjF);
   if (impProjF.isComposite()) {
     // display grayscale, not colored composite
     CompositeImage ci = (CompositeImage) impProjF;
     ci.setMode(IJ.GRAYSCALE);
     impProjF.updateAndDraw();
   }
   displayMinToMax(impProjF);
   impProjF.setTitle(I1l.makeTitle(imps[0], TLA));
   String shortInfo =
       "Maximum intensity projection of log"
           + " (amplitude^2) 2D FFT stack, central region masked,"
           + " rescaled (min-max) to improve contrast of the relevant"
           + " frequency range.";
   results.addImp(shortInfo, impProjF);
   results.addInfo(
       "How to interpret",
       "look for clean 1st & 2nd"
           + " order spots, similar across angles. Note that spot"
           + " intensity depends on image content.");
   return results;
 }
 @Override
 public void run(String arg) {
   ImagePlus imp = IJ.getImage();
   GenericDialog gd = new GenericDialog(name);
   gd.addMessage("Requires SI raw data in OMX (CPZAT) order.");
   gd.addNumericField("angles", angles, 0);
   gd.addNumericField("phases", phases, 0);
   gd.showDialog();
   if (gd.wasCanceled()) return;
   if (gd.wasOKed()) {
     angles = (int) gd.getNextNumber();
     phases = (int) gd.getNextNumber();
   }
   if (!I1l.stackDivisibleBy(imp, phases * angles)) {
     IJ.showMessage(name, "Error: stack size not consistent with phases/angles.");
     return;
   }
   results = exec(imp);
   results.report();
 }