http://imagej.273.s1.nabble.com/plotwindow-drawPlot-plot-incessant-resizing-tp5022995p5023034.html
callback, about 10-20% of the time ImageJ will lockup solid. This is
the imageplus(s) within the ImageListener callback. This never happened
been effected.
lockups are a real joy to debug...
> Hi Fred,
>
> concerning the PlotMaker interface: Whenever the contents or the Roi of
> the source image is updated, the
> public Plot getPlot()
> method of the PlotMaker is called.
> It automatically specifies the following 'useTemplate' flags (in
> addition to any other defined by the plot):
> Plot.COPY_SIZE | Plot.COPY_LABELS | Plot.COPY_AXIS_STYLE |
> Plot.COPY_CONTENTS_STYLE | Plot.COPY_LEGEND | Plot.COPY_EXTRA_OBJECTS
>
> The 'source image' is the one that the user plugin defines in
> public ImagePlus getSourceImage()
>
> The plot.setPlotMaker(this) is not static, i.e., you have to call it
> with the first plot that you create and show. Currently, I think there
> is no simple way to start live plotting of a PlotMaker from java; the
> plot is 'live' only if the user presses the 'live' button. If live
> plotting from the start is desired, we would need a small modification
> of ImageJ.
>
>
> Concerning the RoiListener: The method
> Roi.addRoiListener(this)
> is static, so a RoiListener's roiModified gets calls from all Rois,
> whatever image they belong to. The image is passed with
> roiModified(ImagePlus img, int id)
> Based on the imp, you can select whether the event is of interest for
> your plugin or not. That's the same as for an ImageListener, where you
> should also which ImagePlus was affected (closed/opened/updated).
>
> Therfore, for both, the ImageListener and RoiListener interfaces, make
> sure to de-register with the corresponding
> Roi.removeRoiListener(this);
> ImagePlus.removeImageListener(this);
> Otherwise, your plugin will remain active in the background forever
> (until ImageJ closes) and receive the events, even if you thought it has
> ended all activity. In case of doubt, it does not hurt to call a
> remove...Listener too often (You can also call it without having
> registered with add...Listener).
>
> For the ImageListener interface, in the 1.52u daily build, the static
> method
> ImagePlus.logImageListeners()
> can be used to check for plugins that have forgotten to de-register. You
> can easily call it from Javascript. There is no such method for
> RoiListeners (yet?).
>
>
> Best,
>
> Michael
> ________________________________________________________________
> On 03.03.20 05:26, Fred Damen wrote:
>> Greetings Michael,
>>
>> A mute point now, but, to reproduce, create hyperstack, create roi,
>> start
>> plugin, resize plotwindow, move the roi a dozen times.
>>
>> The plot.userTemplate works great; aggravation level plummets...
>>
>> For the PlotMaker example that you gave, what instigates the drawing of
>> the next plot. I assume that getPlot is called by PlotWindow, but how to
>> setup the trigger?
>>
>> For the RoiListener, who calls roiModified, i.e., static or instance? I
>> found out the hard way that the ImageListener methods were called when
>> any
>> / all imageplus objects were affected; ugly race conditions when trying
>> to
>> close a list of images... use WindowListener instead...
>>
>> The attached plugin serves the same general purpose as the ProfilePlot,
>> albeit in the frame direction. If you collected the same volume (stack
>> of
>> slices) repeatedly and you wanted to know if / how the signal changes
>> through the repeats.
>>
>> Thanks,
>>
>> Fred
>>
>> On Mon, March 2, 2020 4:32 am, Michael Schmid wrote:
>>> Hi Fred,
>>>
>>> there was no problem when I tried it, it works also after resizing the
>>> plot.
>>> Nevertheless, there is an elegant way to make the plot inherit the size
>>> of the previous one shown in the same PlotWindow:
>>>
>>> plot.useTemplate(previousPlot, Plot.COPY_SIZE);
>>>
>>> You can also have it inherit other properties, such as the legend, axis
>>> labels, style, or curves added by the user (who had used the buttons at
>>> the bottom of the plot).
>>> Just use a bitwise OR or the sum of the following flags:
>>>
>>> COPY_SIZE Flag for copying from a template: copy plot size
>>> COPY_LABELS Flag for copying from a template: copy style & text of
>>> axis
>>> COPY_LEGEND Flag for copying from a template: copy legend
>>> COPY_AXIS_STYLE Flag for copying from a template: copy axis style
>>> COPY_CONTENTS_STYLE Flag for copying from a template: copy contents
>>> COPY_EXTRA_OBJECTS Flag for copying PlotObjects (curves...) from a
>>> template if the template has more PlotObjects than the Plot to copy to.
>>>
>>>
>>> In your case (I did not really try to understand your plugin), it seems
>>> that the plot is supposed to react on changes of the Roi? Then there
>>> might be an easier option, just implement the PlotMaker Interface.
>>> The first 40 lines of the Profiler provide an example how to do this:
>>>
>>>
https://github.com/imagej/imagej1/blob/master/ij/plugin/Profiler.java>>>
>>> If a PlotMaker is no option for you, there is also a RoiListener
>>> interface, which tells you when a Roi has changed, so you don't need
>>> the
>>> keyListener & MouseListener, and it will also detect changes of the Roi
>>> caused by, e.g., menu commands.
>>>
>>>
https://github.com/imagej/imagej1/blob/master/ij/gui/RoiListener.java>>>
>>>
>>>
>>> [BTW, I did not understand your other post on CTRL-SHIFT under Fedora;
>>> is this about using the text tool on an image? Can you supply a
>>> screenshot to explain (Plugins>Utilities>Capture Delayed)? Replies in
>>> that thread, please]
>>>
>>> Michael
>>> ________________________________________________________________
>>> On 01.03.20 07:10, Fred Damen wrote:
>>>> Greetings,
>>>>
>>>> I have a plugin that plots the statistics of an ROI through the frame
>>>> dimension. And replots this information when the Roi is altered. The
>>>> trouble is that if you resize the plotwindow and then cause the plot
>>>> to
>>>> be
>>>> redrawn (plotwindow.drawPlot(plot);) the plotwindow appears to insist
>>>> upon
>>>> resizing the window somewhat asynchronously. Sometimes to the
>>>> interactively resized dimensions IRD, but mostly to default
>>>> dimensions.
>>>> So a naive attempt was to query the plotwindow size and set it again
>>>> after
>>>> the drawPlot. This results in the plotwindow more often being resized
>>>> to
>>>> the IRD, alas not always... Figuring that there was one of those race
>>>> conditions going on I put in a IJ.wait statement, then the plotwindow
>>>> mostly resizes to the IRD, albeit the plotwindow does not get updated
>>>> during this wait, and also results in massive flickering. Moving the
>>>> Roi
>>>> with the mouse shows the problem quicker than using the arrow keys,
>>>> but
>>>> within less than 10 redraws the problem happens. Is there a way to
>>>> get
>>>> the plotwindow size not to change on a drawPlot?
>>>>
>>>> This has been happening for the past couple of years on most of the
>>>> systems I run this on. Look for the IJ.wait(10); in the below plugin.
>>>>
>>>> Thanks in advance,
>>>>
>>>> Fred
>>>>
>>>> To reproduce:
>>>> imp = IJ.createImage("HyperStack", "32-bit grayscale-mode", 128, 128,
>>>> 1,
>>>> 1, 10);
>>>> imp.setRoi(new OvalRoi(42,52,42,33));
>>>>
>>>> Run this plugin, resize the plotwindow, then move the Roi:
>>>>
>>>> import ij.*;
>>>> import ij.plugin.*;
>>>> import ij.process.*;
>>>> import ij.gui.*;
>>>> import ij.util.Tools;
>>>> import java.io.*;
>>>> import java.awt.*;
>>>> import java.awt.event.*;
>>>> import java.util.*;
>>>> import ij.measure.*;
>>>> import java.awt.Rectangle;
>>>>
>>>> /**
>>>> This plugin continuously generates Frame-Dimension profile
>>>> plots
>>>> as
>>>> a selection
>>>> is moved or resized through the XY Coordinate Plane.
>>>>
>>>> @author Fred Damen <
[hidden email]>
>>>>
>>>> Version History:
>>>> 2018-04-01: Created
>>>> */
>>>>
>>>> public class F_Profiler implements PlugIn,
>>>> MouseListener,
>>>> MouseMotionListener,
>>>> MouseWheelListener,
>>>> Measurements,
>>>> KeyListener,
>>>> WindowListener,
>>>> ImageListener {
>>>> ImagePlus img;
>>>> PlotWindow pwin;
>>>> public double[] x;
>>>> public double[] y;
>>>> public double[] ye;
>>>> String xLabel;
>>>> String yLabel;
>>>>
>>>> public void run(String arg) {
>>>> img = IJ.getImage();
>>>> int nf = img.getNFrames();
>>>> if (nf<2) {
>>>> IJ.showMessage("Dynamic F-Dimension Profiler", "This
>>>> command
>>>> requires a HyperStack.");
>>>> return;
>>>> }
>>>>
>>>> img.getCanvas().addMouseListener(this);
>>>> img.getCanvas().addMouseMotionListener(this);
>>>> img.getCanvas().addKeyListener(this);
>>>> img.getWindow().addMouseWheelListener(this);
>>>> img.getWindow().addWindowListener(this);
>>>> img.addImageListener(this);
>>>> engaged = true;
>>>> IJ.showStatus("F-Dimension Profile Engaged:
>>>> "+img.getTitle());
>>>>
>>>> x = new double[nf];
>>>> y = new double[nf];
>>>> ye = new double[nf];
>>>> String fu = img.getCalibration().getTimeUnit();
>>>> try {
>>>> ImageStack is = img.getStack();
>>>> for(int f=0; f<nf; f++) {
>>>> String[] strarr =
>>>> is.getSliceLabel(img.getStackIndex(1,1,f+1)).split(",|;",2)[0].split("
>>>> = |=| ",2);
>>>> xLabel = strarr[0]+(fu!="" ? " ("+fu+")" : "");
>>>> x[f] = Float.valueOf(strarr[1]).floatValue();
>>>> //for(int ff=0; ff<f; ff++)
>>>> // if (x[f] == x[ff])
>>>> // throw new Throwable();
>>>> //IJ.log("x["+f+"]="+x[f]);
>>>> }
>>>> }
>>>> catch(Throwable e) {
>>>> xLabel = "frame"+(fu!="" ? " ("+fu+")" : "");
>>>> for(int f=0; f<nf; f++)
>>>> x[f] = f;
>>>> }
>>>>
>>>> yLabel = img.getTitle()+"
>>>> ("+img.getCalibration().getValueUnit()+")";
>>>> if (!updateProfile())
>>>> return;
>>>> positionPlotWindow();
>>>> }
>>>>
>>>> boolean engaged = false;
>>>> void disengage() {
>>>> if (!engaged) return;
>>>> if (img.getWindow() != null) {
>>>> img.getCanvas().removeMouseListener(this);
>>>> img.getCanvas().removeMouseMotionListener(this);
>>>> img.getCanvas().removeKeyListener(this);
>>>> img.getWindow().removeMouseWheelListener(this);
>>>> img.getWindow().removeWindowListener(this);
>>>> img.removeImageListener(this);
>>>> }
>>>> pwin = null;
>>>> engaged = false;
>>>> IJ.showStatus("F-Dimension Profile Disengaged");
>>>> }
>>>>
>>>>
>>>> boolean updateProfile() {
>>>> Roi roi = img.getRoi();
>>>> if (img == null || roi == null) {
>>>> IJ.showStatus("Frame-Dimension Profiles running but
>>>> nothing
>>>> to
>>>> do");
>>>> return true;
>>>> }
>>>>
>>>> if ((pwin != null) && (!pwin.isVisible())) {
>>>> IJ.log("F_Profiler: should not have reached here
>>>> '"+pwin+"'");
>>>> engaged = true;
>>>> disengage();
>>>> return false;
>>>> }
>>>>
>>>> int nf = img.getNFrames();
>>>> int cs = img.getZ();
>>>> double[] yM = new double[nf];
>>>> double[] ym = new double[nf];
>>>> double[] ys = new double[nf];
>>>> ImageStack is = img.getStack();
>>>> Calibration cal = img.getCalibration();
>>>> for(int f=0; f<nf; f++) {
>>>> ImageProcessor ip =
>>>> is.getProcessor(img.getStackIndex(1,cs,f+1));
>>>> ip.setRoi(roi);
>>>> ImageStatistics stats = ImageStatistics.getStatistics(ip,
>>>> MEAN+STD_DEV+MIN_MAX+MEDIAN, cal);
>>>> y[f] = stats.mean;
>>>> ye[f] = stats.stdDev;
>>>> yM[f] = stats.max;
>>>> ym[f] = stats.min;
>>>> ys[f] = stats.median;
>>>> }
>>>>
>>>> Plot plot = new Plot("Frame Profile ("+img.getTitle()+")", xLabel,
>>>> yLabel);
>>>> plot.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
>>>> plot.setXLabelFont(new Font("Comic Sans MS", Font.PLAIN,
>>>> 24));
>>>> plot.setYLabelFont(new Font("Comic Sans MS", Font.PLAIN,
>>>> 24));
>>>>
>>>> plot.setColor(Color.blue);
>>>> plot.setLineWidth(1);
>>>> plot.addPoints(x,y,ye,Plot.X);
>>>> plot.setColor(Color.red);
>>>> plot.setLineWidth(4);
>>>> plot.addPoints(x,y,Plot.X);
>>>>
>>>> plot.setColor(Color.green);
>>>> plot.setLineWidth(2);
>>>> plot.addPoints(x,ym,Plot.BOX);
>>>> plot.addPoints(x,yM,Plot.BOX);
>>>> plot.setColor(Color.black);
>>>> plot.addPoints(x,ys,Plot.CIRCLE);
>>>> plot.setLegend("stddev\nmean\nmax\nmin\nmedian",Plot.AUTO_POSITION);
>>>> if (pwin==null) {
>>>> pwin = plot.show();
>>>> pwin.addWindowListener(this);
>>>> }
>>>> else {
>>>> Dimension s = pwin.getSize();
>>>> pwin.drawPlot(plot);
>>>> pwin.setSize(s);
>>>> IJ.wait(10);
>>>> pwin.setSize(s);
>>>> }
>>>> plot.setLimitsToFit(true);
>>>>
>>>> return true;
>>>> }
>>>>
>>>> void positionPlotWindow() {
>>>> IJ.wait(500);
>>>> if (pwin==null || img==null) return;
>>>> ImageWindow iwin = img.getWindow();
>>>> if (iwin==null) return;
>>>> Dimension screen =
>>>> Toolkit.getDefaultToolkit().getScreenSize();
>>>> Dimension plotSize = pwin.getSize();
>>>> Dimension imageSize = iwin.getSize();
>>>> if (plotSize.width==0 || imageSize.width==0) return;
>>>> Point imageLoc = iwin.getLocation();
>>>> int w = imageLoc.x+imageSize.width+10;
>>>> if (w+plotSize.width>screen.width)
>>>> w = screen.width-plotSize.width;
>>>> pwin.setLocation(w, imageLoc.y);
>>>> iwin.toFront();
>>>> }
>>>>
>>>> public void mousePressed(MouseEvent e) {
>>>> Roi roi = img.getRoi();
>>>> int ix,iy;
>>>> if (roi == null) {
>>>> Point here = img.getCanvas().getCursorLoc();
>>>> ix = here.x;
>>>> iy = here.y;
>>>> }
>>>> else if (roi.getType() == Roi.POINT) {
>>>> Rectangle bounds = roi.getBounds();
>>>> ix = bounds.x;
>>>> iy = bounds.y;
>>>> }
>>>> else {
>>>> updateProfile();
>>>> return;
>>>> }
>>>>
>>>> int nf = img.getNFrames();
>>>> int cs = img.getZ();
>>>> ImageStack is = img.getStack();
>>>> for(int f=0; f<nf; f++) {
>>>> ImageProcessor ip =
>>>> is.getProcessor(img.getStackIndex(1,cs,f+1));
>>>> y[f] = ip.getPixelValue(ix, iy);
>>>> ye[f] = 0;
>>>> }
>>>>
>>>> Plot plot = new Plot("Frame Profile ("+img.getTitle()+")", xLabel,
>>>> yLabel);
>>>> plot.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
>>>> plot.setXLabelFont(new Font("Comic Sans MS", Font.PLAIN,
>>>> 24));
>>>> plot.setYLabelFont(new Font("Comic Sans MS", Font.PLAIN,
>>>> 24));
>>>>
>>>> plot.setColor(Color.blue);
>>>> plot.setLineWidth(4);
>>>>
>>>> Calibration cal = img.getCalibration();
>>>> plot.setJustification(Plot.RIGHT);
>>>> plot.addLabel(0.99,0.99,String.format("%.2f(%d), %.2f(%d),
>>>> (%d)",
>>>> cal.getX(ix),ix,cal.getY(iy),iy,img.getT()));
>>>>
>>>> plot.addPoints(x,y,ye,Plot.X);
>>>> if (pwin==null) {
>>>> pwin = plot.show();
>>>> pwin.addWindowListener(this);
>>>> }
>>>> else {
>>>> Dimension s = pwin.getSize();
>>>> pwin.drawPlot(plot);
>>>> pwin.setSize(s);
>>>> }
>>>> plot.setLimitsToFit(true);;
>>>> }
>>>>
>>>> public void mouseDragged(MouseEvent e) { updateProfile(); }
>>>> public void keyReleased(KeyEvent e) { updateProfile(); }
>>>>
>>>> public void keyPressed(KeyEvent e) {}
>>>> public void keyTyped(KeyEvent e) {}
>>>> public void mouseReleased(MouseEvent e) {}
>>>> public void mouseExited(MouseEvent e) {}
>>>> public void mouseClicked(MouseEvent e) {}
>>>> public void mouseEntered(MouseEvent e) {}
>>>> public void mouseMoved(MouseEvent e) {}
>>>>
>>>> public void mouseWheelMoved(MouseWheelEvent e) { /*
>>>> updateProfile(); */ }
>>>>
>>>> public void windowActivated(WindowEvent e) {}
>>>> public void windowClosed(WindowEvent e) { disengage();}
>>>> public void windowClosing(WindowEvent e) { disengage();}
>>>> public void windowDeactivated(WindowEvent e) {}
>>>> public void windowDeiconified(WindowEvent e) {}
>>>> public void windowIconified(WindowEvent e) {}
>>>> public void windowOpened(WindowEvent e) {}
>>>>
>>>> public void imageClosed(ImagePlus imp) {}
>>>> public void imageOpened(ImagePlus imp) {}
>>>> public void imageUpdated(ImagePlus imp) { /* if (imp==img)
>>>> updateProfile(); */}
>>>> }
>>>>
>>>> --
>>>> ImageJ mailing list:
http://imagej.nih.gov/ij/list.html>>>>
>>>
>>> --
>>> ImageJ mailing list:
http://imagej.nih.gov/ij/list.html>>>
>>
>> --
>> ImageJ mailing list:
http://imagej.nih.gov/ij/list.html>>
>
> --
> ImageJ mailing list:
http://imagej.nih.gov/ij/list.html>