Axis Designations in SetMarquee Operation

The GetMarquee operation allows us to use axis designations (e.g. left, top) to specify the relative settings for the return coordinates. The SetMarquee operation has no equivalent.

I have a window with an image above using left, top and a graph below using its own axes (e.g. hleft, hbottom). I would like to regenerate a previously drawn marquee with SetMarquee based on coordinates returned from GetMarquee relative to (left, top) rather than relative to the entire window.

The feature request is therefore to allow this type of language.

SetMarquee/W=.../A=(left/right axis, top/bottom axis) left, top, right, bottom

 

Update: it seems like the following approach works (until this wish is granted). In an earlier version of this post, the code didn't work because I wasn't converting from pixel coordinates to point coordinates.

 

function setMarqueeByAx(winN,vertAxN,vertBottom,vertTop,horAxN,horLeft,horRight)
    String vertAxN,horAxN,winN
    Variable vertBottom,vertTop,horLeft,horRight
   
    if (strlen(winN) < 1)
        winN=winname(0,1)
    endif
   
    if (strlen(vertAxN) < 1)
        vertAxN = "left"
    endif
   
    if (strlen(horAxN) < 1)
        horAxN = "bottom"
    endif
     
    getwindow $winN, psizeDC
    Variable pixHorRange = V_right-V_left
    getwindow $winN, psize
    Variable pntsHorRange = V_right-V_left  
    Variable pntsPerPix = pntsHorRange / pixHorRange  //ratio seems to always be equal for vertical, so just using horizontal for calculation of the conversion factor
    Variable bottom=pixelFromAxisVal(winN,vertAxN,vertBottom)*pntsPerPix
    Variable top=pixelFromAxisVal(winN,vertAxN,vertTop)*pntsPerPix
    Variable left=pixelFromAxisVal(winN,horAxN,horLeft)*pntsPerPix
    Variable right=pixelFromAxisVal(winN,horAxN,horRight)*pntsPerPix
       
    SetMarquee/W=$winN left, top, right, bottom
end

 

In reply to by gsb

gsb wrote:

Update: it seems like the following approach works (until this wish is granted). In an earlier version of this post, the code didn't work because I wasn't converting from pixel coordinates to point coordinates.

Thanks. I am using a structure and a function call to populate either marquee or drawing coordinates.

// structure to collect marquee or hRoI coordinates
Structure MarqueeCoordinates
    variable hasmarquee
    variable hasdrawing
    variable paleft
    variable paright
    variable patop
    variable pabottom
    variable pgleft
    variable pgright
    variable pgtop
    variable pgbottom
EndStructure

// fill the structure
Function GetMCCoordinates(mc)
    Struct MarqueeCoordinates &mc
   
    GetMarquee/W=$k_graphName/Z
    mc.hasmarquee = v_flag
    DrawAction/W=$k_graphName/L=ProgFront getgroup=hRoI, extractOutline
    mc.hasdrawing = v_flag
   
    variable pntsh, pxlsh, pntsppxl

    // hRoI drawing overrides marquee
    if (mc.hasdrawing == 1)
        wave w_polyx, w_polyy
        mc.pgleft=w_polyx[0]
        mc.pgright=w_polyx[1]
        mc.pgtop=w_polyy[1]
        mc.pgbottom=w_polyy[2]
        getwindow $k_graphName, psizeDC
        pxlsh = V_right-V_left
        getwindow $k_graphName, psize
        pntsh = V_right-V_left  
        pntsppxl = pntsh / pxlsh
        mc.paleft = PixelFromAxisVal(k_graphName,"left",mc.pgleft)*pntsppxl
        mc.patop = PixelFromAxisVal(k_graphName,"top",mc.pgtop)*pntsppxl
        mc.paright = PixelFromAxisVal(k_graphName,"left",mc.pgright)*pntsppxl
        mc.pabottom = PixelFromAxisVal(k_graphName,"top",mc.pgbottom)*pntsppxl
        killwaves/Z w_polyx, w_polyy
        return 0
    endif  
   
    // no hRoI drawing or marquee
    if (mc.hasmarquee == 0)
        mc.paleft = NaN; mc.patop = NaN; mc.paright = NaN; mc.pabottom = NaN
        mc.pgleft = NaN; mc.pgtop = NaN; mc.pgright = NaN; mc.pgbottom = NaN
        return 0
    endif
   
    // marquee
    mc.paleft = v_left
    mc.paright = v_right
    mc.patop = v_top
    mc.pabottom = v_bottom 
    GetMarquee/W=$k_graphName/Z left,top
    mc.pgleft = v_left
    mc.pgright = v_right
    mc.pgtop = v_top
    mc.pgbottom = v_bottom 
    return 0
end

I can draw a marquee on an image to restrict a histogram region. I need the graph coordinates to compute the image mask. I can get those and the absolute coordinates from the GetMarquee operation. As needed, I lock down the RoI as a drawing (hRoI). For this function, I also need the graph coordinates. When all is done, I can clear the RoI drawing. I want to restore the marquee to those coordinates. But I need the absolute coordinates to do a SetMarquee. Unfortunately ... :-( ... , the extractOutline flag pulls the drawing using graph coordinates, not absolute coordinates.

Hence, the desire to have SetMarquee be aware of placements in graph coordinates as (most) other operations also are.

Jeff- I have just implemented in Igor 9:

SetMarquee/HAX=axisname/VAX=axisname left, top, right, bottom

Using separate flags allows you to mix points and axis coordinates. That might or might not be particularly useful, but seems to me that unnecessary restrictions will only generate future enhancement requests :)

John: Thanks. I would have thought with one flag to handle the independent option with star or blank ...

/AX=(left,*)   ... or ...  /AX=(left,)   // set vertical on the axis titled left and horizontal as absolute top/bottom

/AX=(*,*) ... or ... /AX=()   // clear all axes designations (set to absolute)

 

I use the GetMarquee left, top operation for a marquee on an image. Why does it return values of v_left ... that are offset by -0.5? For example, when I force it to set at what I think is left=0, top=0, I read back -0.5, -0.5 rather than 0, 0?!?! I presume the right and bottom are also "offset" by -0.5 because the values also end with 0.5 (e.g. 615.5 rather than 615 or 616).

Is the marquee coordinates to be read as being "left and above the next whole number pixel" in this case?

How will this be handled for the new flags with the /HAX=top and /LAX=left designations? What will be the value when we would use SetMarquee/HAX=left 0,... to place the marquee at 0,0 and then read it back using GetMarquee left, top? Will we get v_left = 0 or will we get v_left = -0.5?

Jim: I'll pull out a working example from my Image Tools package and try to post it by later this week or weekend.

Ok. I think I have it figured out. Help me here where I am wrong. This is for an image in a window.

GetMarquee - returns window coordinates as integer numbers
GetMarquee left, top - returns graph coordinates as real numbers

SetMarquee - takes window coordinates as integer numbers OR rounds inputs to integer numbers

The result is that I cannot position the marquee to WHOLE NUMBER (integer) values of a position in image pixels.

GetMarquee
--> Window: 138  212  395  451
GetMarquee left, top
--> Graph: 497.126  513.508  1528.5  1473.26
// try to force to whole number pixels in graph (e.g. 498, 513, 1529, 1473)
SetMarquee 137.889, 212.205, 394.881, 451.42
GetMarquee
--> Window: 138  212  395  451
GetMarquee left, top
--> Graph: 497.126  513.508  1528.5  1473.26

I'll work with this new knowledge in my code.

Thanks!