Bypassing plugin dialog within macro

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Bypassing plugin dialog within macro

Sidney Rempel
I'm working on a macro that includes a plugin but I would like to bypass the user value input dialog and just have it use predetermined values.

The plugin is Local Transformation found here:
http://bigwww.epfl.ch/sage/soft/localnormalization/

It dates back to 2002 but works fine on the latest ImageJ version.

Included with this plugin are:
LocalNormalization_$Convolver
LocalNormalization_

and then another subdirectory named imageaccess which contains the files:
ImageAccessTools
ImageAccess

Within the macro, running this plugin comes up in the Macro recorder as:
run("LocalNormalization ");

When the macro is run, a dialog comes up requesting two sigma values as indicated by slider bars.

Is there any way I can pass set values to this request and have the dialog close and continue on?

Sorry if this seems elementary but I am not a programmer. The macro runs fine otherwise

Thanks in advance for any advice.
Reply | Threaded
Open this post in threaded view
|

Re: Bypassing plugin dialog within macro

Michael Schmid
Hi Sidney,

it seems that this plugin does not use the GenericDialog class for  
the user interface, so it does not work with macros. I have not found  
any sources on the web page to change that - maybe you could contact  
the author? It seems that he is still at the EPFL.
   http://bigwww.epfl.ch/sage/

Option 2 -You could have a look at the IJ_Robot to automate it.

Option 3 - As the action done by the plugin is rather simple, it  
would be probably easiest to rewrite it. This is also possible as a  
macro:

The first action is a highpass filter, already available at
   http://imagejdocu.tudor.lu/doku.php?
id=plugin:filter:highpass_filter:start

Then duplicate the highpass-filtered image, square it, run a Gaussian  
Blur with sigma2, take the square root, and use ImageCalculator to  
divide the highpass-filtered image by the outcome of this operation.

Michael
________________________________________________________________

On 3 Mar 2011, at 19:11, Sidney Rempel wrote:

> I'm working on a macro that includes a plugin but I would like to  
> bypass the user value input dialog and just have it use  
> predetermined values.
>
> The plugin is Local Transformation found here:
> http://bigwww.epfl.ch/sage/soft/localnormalization/
>
> It dates back to 2002 but works fine on the latest ImageJ version.
>
> Included with this plugin are:
> LocalNormalization_$Convolver
> LocalNormalization_
>
> and then another subdirectory named imageaccess which contains the  
> files:
> ImageAccessTools
> ImageAccess
>
> Within the macro, running this plugin comes up in the Macro  
> recorder as:
> run("LocalNormalization ");
>
> When the macro is run, a dialog comes up requesting two sigma  
> values as indicated by slider bars.
>
> Is there any way I can pass set values to this request and have the  
> dialog close and continue on?
>
> Sorry if this seems elementary but I am not a programmer. The macro  
> runs fine otherwise
>
> Thanks in advance for any advice.
Reply | Threaded
Open this post in threaded view
|

Re: Bypassing plugin dialog within macro

Sidney Rempel
In reply to this post by Sidney Rempel
Hi Michael and Wayne,

Thanks for the quick replies.

I will try to contact the original author and see if he has any solutions.

I was looking into IJ_Robot but will need to read up on that and try some tests before I feel comfortable with it. With my macro, there's going to be a lot going on on-screen so it might increase the chance of errors. Also, the Local Normalization dialog uses sliders, not regular keyboard input. I'm not sure if that's doable with IJ_Robot.

It sounds like your option 3, to replicate the results might be the way to go right now.

The Normalization occurs early in the macro sequence so being on hand to enter the values is not extremely inconvenient, just one step away from complete automation.

Thanks again!
Sidney
Reply | Threaded
Open this post in threaded view
|

Re: Bypassing plugin dialog within macro

Sidney Rempel
In reply to this post by Sidney Rempel
Hi Michael,
I tried to compile and install the High Pass filter but received these errors:

error: error reading C:\PROGRA~1\ImageJ\plugins\Input-Output\itext-1.4.8.jar; cannot read zip file
C:\Program Files\ImageJ\plugins\Filters\High_pass.java:125: warning: [deprecation] getBoundingRect() in ij.gui.Roi has been deprecated
                roi.getBoundingRect().width==ip.getWidth() && roi.getBoundingRect().height==ip.getHeight()));
                   ^
C:\Program Files\ImageJ\plugins\Filters\High_pass.java:125: warning: [deprecation] getBoundingRect() in ij.gui.Roi has been deprecated
                roi.getBoundingRect().width==ip.getWidth() && roi.getBoundingRect().height==ip.getHeight()));

Not sure what I'm missing here...
Reply | Threaded
Open this post in threaded view
|

Re: Bypassing plugin dialog within macro

Michael Schmid
Hi Sidney,

it seems that your itext-1.4.8.jar is corrupted, try to move it out  
of the plugins folder before compiling (you can put it back later,  
but probably it won't work anyhow). Maybe a file downloaded with  
Internet Explorer? (Firefox does not corrupt .zip or .jar files on  
download).

I have also quickly created my own version of Local_Normalization  
(pasted at the end; the mailing list does not allow me to attach it).
It is similar to the one of Daniel Sage, but uses different grayscale  
for the output:
In my version, the background (zero) is always the same, at 128 (8-
bit, RGB), 32768 (16-bit) or 0 (float images), and all images are  
normalized the same way (full image range is 8 sigma).

In Daniel Sage's version, the grayscale is adjusted so that the image  
data fit into the range.

Also, there are small differences near the edge, but that should not  
matter.

Have fun with it,


Michael
________________________________________________________________

On 3 Mar 2011, at 22:44, Sidney Rempel wrote:

> Hi Michael,
> I tried to compile and install the High Pass filter but received  
> these errors:
>
> error: error reading C:\PROGRA~1\ImageJ\plugins\Input-Output
> \itext-1.4.8.jar; cannot read zip file
> C:\Program Files\ImageJ\plugins\Filters\High_pass.java:125:  
> warning: [deprecation] getBoundingRect() in ij.gui.Roi has been  
> deprecated
>                 roi.getBoundingRect().width==ip.getWidth() &&  
> roi.getBoundingRect().height==ip.getHeight()));
>                    ^
> C:\Program Files\ImageJ\plugins\Filters\High_pass.java:125:  
> warning: [deprecation] getBoundingRect() in ij.gui.Roi has been  
> deprecated
>                 roi.getBoundingRect().width==ip.getWidth() &&  
> roi.getBoundingRect().height==ip.getHeight()));
>
> Not sure what I'm missing here...

________________________________________________________________


import ij.plugin.filter.ExtendedPlugInFilter;
import ij.plugin.filter.PlugInFilterRunner;
import ij.plugin.filter.GaussianBlur;
import ij.*;
import ij.gui.GenericDialog;
import ij.gui.DialogListener;
import ij.process.*;
import java.awt.*;
import java.awt.event.*;

/** Local Normalization, as described in
*   http://bigwww.epfl.ch/sage/soft/localnormalization/
*
* Restrictions:
* Only works on the whole image, ROIS are ignored
*
* Code by Michael Schmid, version 2011-03-03
*/

public class Local_Normalization implements ExtendedPlugInFilter,  
DialogListener {
     private static double sigma1 = 10, sigma2 = 20; //filter parameters
     private final int flags = DOES_ALL|CONVERT_TO_FLOAT|SNAPSHOT|
KEEP_PREVIEW|FINAL_PROCESSING;
     private ImagePlus imp;
     private boolean previewing;
     private GaussianBlur gb = new GaussianBlur();


     /**
      * This method is called by ImageJ for initialization.
      * @param arg Unused here. For plugins in a .jar file this  
argument string can
      *            be specified in the plugins.config file of  
the .jar archive.
      * @param imp The ImagePlus containing the image (or stack) to  
process.
      * @return    The method returns flags (i.e., a bit mask)  
specifying the
      *            capabilities (supported formats, etc.) and needs  
of the filter.
      *            See PlugInFilter.java and ExtendedPlugInFilter in  
the ImageJ
      *            sources for details.
      */
     public int setup(String arg, ImagePlus imp) {
         if (IJ.versionLessThan("1.38x"))        // generates an  
error message for older versions
             return DONE;
         this.imp = imp;
         if (arg.equals("final"))
             adjustGrayScale();
         return flags;
     }

     /** Called by ImageJ after setup. */
     public int showDialog(ImagePlus imp, String command,  
PlugInFilterRunner pfr) {
         ImageProcessor ip = imp.getProcessor();
         double min = ip.getMin();
         double max = ip.getMax();
         GenericDialog gd = new GenericDialog(command+" Options");
         gd.addSlider("High Pass Radius (local mean)", 1.0, 100.0,  
sigma1);
         gd.addSlider("Variance Radius", 1.0, 100.0, sigma2);
         gd.addPreviewCheckbox(pfr);     // makes the filter ready  
for preview
         gd.addDialogListener(this);     // the DialogItemChanged  
method will be called on user input
         previewing = true;
         gd.showDialog();                 // display the dialog;  
preview runs in the background now
         previewing = false;
         if (gd.wasCanceled()) {
             ip.setMinAndMax(min, max);          // revert to  
original settings
             return DONE;
         }
         IJ.register(this.getClass());   // protect static class  
variables (filter parameters) from garbage collection
         return IJ.setupDialog(imp, flags);   // ask whether to  
process all slices of stack (if a stack)
     }

     /** Called after modifications to the dialog. Returns true if  
valid input. */
     public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
         sigma1 = gd.getNextNumber();
         sigma2 = gd.getNextNumber();
         return (!gd.invalidNumber() && sigma1>0 && sigma2>0);
     }

     /** Process a FloatProcessor (with the CONVERT_TO_FLOAT flag,  
ImageJ does the conversion to float).
      *  Called by ImageJ for each stack slice (when processing a  
full stack); for RGB also called once for each color. */
     public void run(ImageProcessor ip) {
         if (Thread.currentThread().isInterrupted()) return;
         gb.blurGaussian(ip, sigma1, sigma1, 0.01);
         if (Thread.currentThread().isInterrupted()) return;
         snapshotMinusCurrent(ip);
         if (Thread.currentThread().isInterrupted()) return;
         ImageProcessor ip2 = ip.duplicate();
         if (Thread.currentThread().isInterrupted()) return;
         ip2.sqr();
         if (Thread.currentThread().isInterrupted()) return;
         gb.blurGaussian(ip2, sigma2, sigma2, 0.01);
         if (Thread.currentThread().isInterrupted()) return;
         ip2.sqrt();
         if (Thread.currentThread().isInterrupted()) return;
         float offset = 128;
         float factor = 32;  //so we have 4 sigma inside the  
displayable grayscale range
         if (imp.getType()==ImagePlus.GRAY32) {
             offset = 0; factor = 1;
         } else if (imp.getType()==ImagePlus.GRAY16) {
             offset = 128*256; factor = 32*256;
         }
         divide(ip, ip2, factor, offset);
         if (previewing) adjustGrayScale();
         return;
        }

     private void snapshotMinusCurrent(ImageProcessor ip) {
         float[] pixels = (float[])ip.getPixels();
         float[] snapshot = (float[])ip.getSnapshotPixels();
         for (int i=0; i<pixels.length; i++)
             pixels[i] = snapshot[i]-pixels[i];
     }
     private void divide(ImageProcessor ip1, ImageProcessor ip2,  
float factor, float offset) {
         float[] pixels1 = (float[])ip1.getPixels();
         float[] pixels2 = (float[])ip2.getPixels();
         for (int i=0; i<pixels1.length; i++)
             pixels1[i] = pixels1[i]*factor/pixels2[i]+offset;
     }

     //make FloatProcessor nice to see
     private void adjustGrayScale() {
         ImageProcessor ip = imp.getProcessor();
         if (imp.getType()==ImagePlus.GRAY32)
             ip.setMinAndMax(-2, 2);
         else if (imp.getType()==ImagePlus.GRAY16)
             ip.setMinAndMax(0, 0xffff);
     }

     /** Called by ImageJ to set the number of calls to run(ip)  
corresponding to 100% of the progress bar */
     public void setNPasses(int nPasses) {
         gb.setNPasses(2*nPasses);
     }

}
Reply | Threaded
Open this post in threaded view
|

Re: Bypassing plugin dialog within macro

Sidney Rempel
In reply to this post by Sidney Rempel
Hello again,

Thanks for the response again Michael.

You'll have to excuse my ignorance, but to try your Normalization, am I to cut/paste the bottom of your last message into a text, save it as a .java file, and then Compile and Run it?

It turns out that the other Local Normalization I was trying to use won't handle images c. 75MB. Not sure why. IJ has allocated 1500MB of memory. These are 8 bit grayscale images I'm working with by the way.

Anyway, I will try your plugin instead in the meantime.

Thank You very much!