Access user drawed objects by programming code
flashbanger
i want to use Igor to analize some structures in an image. Therefore i am drawing some lines (more than 100 lines) onto a drawing layer with the line-drawing tool. Now i want to do some statistics on the lines for example calculate the length of the lines, crossing points, etc. Sadly i can't find any example how to do that and if it is even possible to for example to generate a wave which contains all coordinates of the user drawed lines so that i could analize the properties of each line in a loop.
Does anyone know how this can be done?
Best,
flashbanger
In your image graph, first specify the drawing coordinates to be the left (y) and bottom (x) axes, with whatever line appearance you wish.
Draw all your lines.
Exit drawing mode, and create the graph recreation macro. In that macro each line drawing command will look like:
DrawLine -0.778770949720671,-0.385988483685221,0.489385474860335,0.550671785028791
Save the macro in a Notebook, and then save the Notebook as a text file.
Load and parse the text file to extract the numerical data following each "DrawLine" string, converting each pair vertex string into two numerical N=2 x-waves and y-waves (or use a multidimensional wave to accumulate all the data). (You may also try to parse and extract the data directly from the Notebook, without saving an external file.)
The main idea is to use the recreation macro to access the drawing data. Subsequent processing will be your burden. I hope someone else may suggest an easier approach.
April 19, 2018 at 09:32 am - Permalink
Drawing that many lines using drawing tools can get old pretty quickly and the result is not ideal for further processing. On the other hand, if you use a pair of waves say YYY plotted vs. XXX and edit these curves (possibly adding NaNs where you want to end a segment), leaves you with numeric representation in a coordinate system that matches the image. You can also pre-populate the wave programmatically (especially the NaNs). To find out more about this execute
I hope this helps,
A.G.
WaveMetrics, Inc.
April 19, 2018 at 10:18 am - Permalink
•img=enoise(1) //just fill it with some values to look at
•newimage/k=1/N=clickWin img
•disp_storeClickLocs("clickWin","top","left","clickLocs",1) //allows tracing by mouse clicks with the control key down
function disp_storeClickLocs(winN,horizAxName,vertAxName,mouseLocWvRef,showOverlay)
String winN //name of window
String horizAxName,vertAxName //name of horizontal and vertical axes for coordinate plane
String mouseLocWvRef //name of a wave to store the horizontal and vertical coordinates in (created if it does not exist)
Variable showOverlay //pass true to overlay click points on window
setwindow $winN userdata(mouseLocWvRef)=mouseLocWvRef
setwindow $winN userdata(horizAxName)=horizAxName
setwindow $winN userdata(vertAxName)=vertAxName
setwindow $winN userdata(showOverlay)=num2str(showOverlay)
setwindow $winN hook(disp_storeClickHook)=disp_storeClickHook
end
//main hook function to track when (ctrl) clicks occur and store their location
function disp_storeClickHook(s) //main
STRUCT WMWinHookStruct &s
Variable mouseUp = s.eventcode == 5
Variable ctrlClick = s.eventmod & 2^3
if (!mouseUp || !ctrlClick)
return 0 //ignore all other events
endif
String mouseLocWvRef = GetUserData(s.winname, "", "mouseLocWvRef" )
String horizAxName = GetUserData(s.winname, "", "horizAxName" )
String vertAxName = GetUserData(s.winname, "", "vertAxName" )
Variable showOverlay = str2num(GetUserData(s.winname, "", "showOverlay" ))
Variable row
if (!WaveExists($mouseLocWvRef))
make/o/d/n=(1,2) $mouseLocWvRef/wave=mouseLocWv
row=0
SetDimLabel 1,0,$horizAxName,mouseLocWv
setdimlabel 1,1,$vertAxName,mouseLocWv
else
WAVE mouseLocWv=$mouseLocWvRef
row=dimsizE(mouseLocWv,0)
redimension/n=(row+1,-1) mouseLocWv
endif
mouseLocWv[row][0] = disp_getMouseLoc(s,horizAxName)
mouseLocWv[row][1] = disp_getMouseLoc(s,vertAxName)
//check that mouseLocWv is plotted if it should be
if (showOverlay && !itemsinlist(WaveList(mouseLocWvRef, ";", "WIN:"+s.winname)))
String horAxisType = StringByKey("AXTYPE", AxisInfo(s.winName, horizAxName))
String vertAxisType = StringByKey("AXTYPE", AxisInfo(s.winName, vertAxName))
if (stringmatch(horAxisType,"right") && stringmatch(vertAxisType,"bottom"))
appendtograph/R $mouseLocWvref[][1] vs $mouseLocWvref[][0]
elseif (stringmatch(horAxisType,"left") && stringmatch(vertAxisType,"bottom"))
appendtograph $mouseLocWvref[][1] vs $mouseLocWvref[][0]
elseif (stringmatch(horAxisType,"right") && stringmatch(vertAxisType,"top"))
appendtograph/R/T $mouseLocWvref[][1] vs $mouseLocWvref[][0]
else //last combination is left top
appendtograph/T $mouseLocWvref[][1] vs $mouseLocWvref[][0]
endif
endif
end
//helper function to get mouse click locations
function disp_getMouseLoc(s, axisNameStr)
STRUCT WMWinHookStruct &s
String axisNameStr //name of axis of interest
String axisType = StringByKey("AXTYPE", AxisInfo(s.winName, axisNameStr))
//determine if vertical, return y position if so, x position if not
Variable isVert = stringmatch(axisType, "left") || stringmatch(axisType, "right")
//find proportion along vert or horiz
Variable prop; getWindow $s.winName, psizeDC
if (isVert)
prop = (s.mouseLoc.v - V_top) / (V_bottom - V_top)
else
prop = (s.mouseLoc.h - V_left) / (V_right - V_left)
endif
//find start and end values of axis as shown
GetAxis/Q $axisNameStr; Variable shownRange, rangeStart, relPos
if (V_max > V_min) //standard direction axis, low to high ordering
shownRange = V_max - V_min
rangeStart = V_min
else
shownRange = V_min - V_max
rangeStart = V_max
endif
if (shownRange == 0)
relPos = nan
else
relPos = rangeStart + prop*shownRange
endif
return relPos
end
April 19, 2018 at 10:56 am - Permalink