UpdtDisplay: recursion attempted printed in Command Window

I've use a hook function which calls a function after a graph has been modified. Each time the graph is modified(I'm moving a trace), four instances of "UpdtDisplay: rescursion attempted" is printed in the command line. What is causing the print at the command line and can I get it to stop?
Here is the code:

Function GraphNow()
    setwindow graph1 hook=updateFakeBand
end

Function updateFakeBand(infostr)
    string infostr
   
    string event=StringByKey("EVENT",infostr)
    strswitch(event)
        case"modified":
            SVar TW=root:LaneName
            wave w=$TW
            createimageframe(w)
    break
    endswitch

return 0
   
end
Is it possible that the hook gets called before createimageframe() has finished?

If so, use a global variable to control recursion, something like this:
Function GraphNow()
    setwindow graph1 hook=updateFakeBand
    Variable/G updateFakeBandRunning = 0
end
 
Function updateFakeBand(infostr)
    string infostr

    NVAR updateFakeBandRunning
    if (updateFakeBandRunning)
        return 0                // avoid re-entrant call
    endif
    updateFakeBandRunning = 1
 
    string event=StringByKey("EVENT",infostr)
    strswitch(event)
        case"modified":
            SVar TW=root:LaneName
            wave w=$TW
            createimageframe(w)
    break
    endswitch
 
    updateFakeBandRunning = 0
return 0
 
end

You could put the recursion block into createimageframe(), but I don't have the code for it, so I put it into updateFakeBand(). This is one of the few reasons to use a global variable!

On a side note, in new code you should really use named hook functions that take a structure as input. They are more reliable and are more likely to get new features.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Hi John,

Thanks for the reply. I tried your code and still have problem. I'm attaching a screen shot of what I'm doing, as well as the additional code (createimageframe).

Function CreateImageFrame(w)
    wave w
    wave pfl=root:packages:wmimprocess:lineprofile:profile
    variable n, framelength
    nVar GS=root:greyscalevalue
    framelength=dimsize(w,0)
    make/o/n=(framelength,5) FalseBandImage
    duplicate/o pfl, LaneProfile
    LaneProfile=-LaneProfile
    do
        FalseBandImage[][n]=pfl[p]
        n+=1
    while(n<5)
    dowindow/R/K Fake
    Display/n=Fake/w=(150,50,415,600); appendimage FalseBandImage
    Modifygraph/w=Fake swapxy=1, tick=3,noLabel=2,margin(left)=216
    ModifyImage FalseBandImage ctab= {*,GS,Grays,1}
    SetAxis/A/R left
    Display/FG=(FL,FT,FR,FB)/HOST=#/VERT LaneProfile
    SetAxis/A/R left
    ModifyGraph tick(left)=3,axisEnab(bottom)={0,0.8},nolabel(left)=2,mode=7,rgb=(0,39168,0),hbFill=5
    label bottom "Signal Intensity"
end

Function GraphNow()
    setwindow graph0 hook=updateFakeBand
    Variable/G updateFakeBandRunning = 0
end
 
Function updateFakeBand(infostr)
    string infostr
 
    NVAR updateFakeBandRunning
    if (updateFakeBandRunning)
        return 0                // avoid re-entrant call
    endif
    updateFakeBandRunning = 1
 
    string event=StringByKey("EVENT",infostr)
    strswitch(event)
        case"modified":
            SVar TW=root:LaneName
            wave w=$TW
            createimageframe(w)
    break
    endswitch
 
    updateFakeBandRunning = 0
return 0
 
end
Concept.jpg (280.87 KB)
johnweeks wrote:

On a side note, in new code you should really use named hook functions that take a structure as input. They are more reliable and are more likely to get new features.


And don't forget, named hook functions should return 1 not 0 to indicate they have accomplished something.

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
OK- I'm not exactly certain why that triggers the Recursion Attempted message, but killing and creating graphs inside a graph Modified event may not be the best thing to do. You can get around it using Execute/P to put off running the function until all the excitement is done. Instead of this:
            SVar TW=root:LaneName
            wave w=$TW
            createimageframe(w)

do this:
            SVar TW=root:LaneName
            Execute/P "createimageframe("+TW+")"

You'll find that this litters your history with calls to createimageframe. But you'll see what it's doing that way. To get rid of the litter, add /Q after /P.

But really, you don't want to do it this way. Destroying and re-making the graph is time-consuming, and as you see, fraught with difficulties. I would note the documentation for DoWindow/R, where it says:
"However, /R does nothing if a macro or function is running." I think all you want is the action of /K, so that's really not an issue, but still...

I would use the GraphNow() function to create the Fake graph, then in updateFakeBand() just modify the waves being displayed in Fake.

OK- I just ran Igor under a debugger so I could figure out why your code triggers that message. It should have been obvious (to me)... The Modified event comes during a display update, when Igor notices that your graph has been modified. But your Display command also triggers a display update, when Igor is already in the middle of a display update. And that's why Execute/P fixes it: it puts off the destruction and creation of a graph until after the window hook function is finished, which will be after the original display update is finished.

I still recommend doing the job differently!

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
jjweimer wrote:
And don't forget, named hook functions should return 1 not 0 to indicate they have accomplished something.

Yeah, generally that's true. In this case, he's just trying to respond to an event and doesn't want to modify Igor's actions. If you only want to know when to do something, returning zero is correct- it lets Igor do its thing, and you can do your thing.

If you're responding to key presses or mouse clicks, on the other hand, you probably want to return 1 to prevent Igor from, say, launching a dialog or entering text when you want to use the mouse click or character.

In this particular case, returning 1 won't do anything- Igor is just informing you that a graph has already been modified and you can't keep Igor from doing anything in this case.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
John,

Thanks for the details. I will implement your correction as well as try to achieve the same result by other means.

Cheers,

Clayton
This should be very easy. I see no reason why you would want to create a graph where all you do is show some updated values of two waves (where the update happens automatically when you write into the waves). Create the graph once at the start (or upon the first call) in a separate function and just leave all the graph stuff out of the hook function unless you really want to modify something on the graph every time (which I don't see here).