Highlight a data point on all graphs
aclight
Usage: You need to set a named window hook on all graph windows that you want to be able to click on a data point and have it highlighted in all other graph windows. To do this, from the Igor command line execute the following code (replacing Graph0 with the name of the graph:
SetWindow Graph0 hook(HighlightPoint)=HighlightDataPoint_Hook
Here's some quick code to give an example. Paste it into the command line and execute it. Then Shift-click on a point of the trace in Graph10 and see that in both Graph10 and Graph11 a tag is placed at that data point. Shift-click again to remove the tag in both windows.
Make testwave1 = p, testwave2 = sin(x)
Display/N=Graph10 testwave1, testwave2
Display/N=Graph11 testwave1, testwave2
AutoPositionWindow/R=Graph10 Graph11
SetWindow Graph10 hook(HighlightPoint)=HighlightDataPoint_Hook
Display/N=Graph10 testwave1, testwave2
Display/N=Graph11 testwave1, testwave2
AutoPositionWindow/R=Graph10 Graph11
SetWindow Graph10 hook(HighlightPoint)=HighlightDataPoint_Hook
static Constant HIGHLIGHT_CLICK_MODIFIERS = 2 // Shift key is down
//**
// Window hook function that responds to clicking on a graph
// and then causes a data point to be highlighted.
// @param s
// An instance of the WMWinHookStruct structure.
// @return
// A non-zero value if this function handled the event or zero
// if it did not.
//*
Function HighlightDataPoint_Hook(s)
STRUCT WMWinHookStruct &s
Variable hookResult
// Only handle the event if the proper modifier key(s) were pressed.
if (s.eventCode == 5 && s.eventMod == HIGHLIGHT_CLICK_MODIFIERS)
// Determine the trace and wave that were clicked on and
// the point index where the user clicked.
String hitInfo = TraceFromPixel(s.mouseLoc.h, s.mouseLoc.v, "WINDOW:" + s.winName)
if (strlen(hitInfo) > 0)
String traceName = StringByKey("TRACE", hitInfo, ":", ";")
Variable hitPoint = NumberByKey("HITPOINT", hitInfo, ":", ";")
if (strlen(traceName) > 0 && numtype(hitPoint) == 0)
WAVE/Z targetWave = TraceNameToWaveRef(s.winName, traceName)
if (WaveExists(targetWave))
HighlightDataPoint(targetWave, hitPoint, s.winName)
hookResult = 1
endif
endif
endif
endif
return hookResult
End
//**
// Main utility function that is called to highlight (or remove the highlight from) a
// data point on a wave in a number of graph windows.
//
// @param targetWave
// A wave reference to the wave the user clicked on.
// @param pointIndex
// A variable containing the point value at which
// the tag should be added or removed.
// @param activeGraphName
// A string containing the name of the graph on which
// the user clicked. This graph will always have the tag
// toggled on or off.
// @param targetGraphList
// [OPTIONAL] A string containing a semicolon separated list
// of graphs which should have a tag added or removed if the
// specified wave is displayed on the graph. If this parameter
// is not specified all graph windows will be acted upon.
// *
Function HighlightDataPoint(targetWave, pointIndex, activeGraphName, [targetGraphList])
WAVE targetWave
Variable pointIndex
String activeGraphName
String targetGraphList
// If the parameter targetGraphList is not specified, then
// call a function to get target windows.
if (ParamIsDefault(targetGraphList))
targetGraphList = GetTargetGraphList()
endif
// Make sure that the active graph (the one the user used to
// trigger this function being called) is included in the list
// of graphs on which the highlighting of the point should be
// toggled.
if (WhichListItem(activeGraphName, targetGraphList, ";") < 0)
targetGraphList = AddListItem(activeGraphName, targetGraphList, ";", inf)
endif
Variable numGraphs = ItemsInList(targetGraphList, ";")
Variable n, traceIndex, numTraces
String currentGraphName
String thisWaveFullName
String targetWaveFullName
String traceList, currentTraceName
For (n=0; n<numGraphs; n+=1)
currentGraphName = StringFromList(n, targetGraphList, ";")
// Make sure this is actually a graph.
If (WinType(currentGraphName) != 1)
continue
endif
// Iterate through the traces on the graph to find
// if any of them are based on targetWave and if so then
// append or remove tags on the graph at the specified point.
// NOTE: This won't work as expected for traces
// that are XY pairs.
traceList = TraceNameList(currentGraphName, ";", 5) // Include normal graph traces and omit hidden traces
numTraces = ItemsInList(traceList, ";")
targetWaveFullName = GetWavesDataFolder(targetWave, 2)
thisWaveFullName = ""
traceIndex = 0
For (traceIndex = 0; traceIndex < numTraces; traceIndex +=1)
currentTraceName = StringFromList(traceIndex, traceList, ";")
WAVE/Z thisWave = TraceNameToWaveRef(currentGraphName, currentTraceName)
// If thisWave is NULL for any reason, skip it.
if (!WaveExists(thisWave))
continue
endif
// Determine if targetWave and thisWave are the same wave.
thisWaveFullName = GetWavesDataFolder(thisWave, 2)
if (cmpstr(thisWaveFullName, targetWaveFullName) == 0)
// Toggle the presence of tags for the given point on the specified graphs.
RemoveOrAddTagToTrace(currentGraphName, currentTraceName, pointIndex)
endif
EndFor
EndFor
End
//**
// Toggles the presence of a tag on the specified trace at the specified point.
//
// @param graphName
// A string containing the full name of the graph.
// @param traceName
// A string containing the name of the trace.
// @param pointIndex
// A variable containing the point value at which
// the tag should be added or removed.
//
// @return
// 1 if a tag was removed, 0 if it was added, or NaN if there was
// an error, such as an invalid graph or trace name.
//*
Function RemoveOrAddTagToTrace(graphName, traceName, pointIndex)
String graphName
String traceName
Variable pointIndex
// Make sure graph exists.
if (WinType(graphName) != 1)
return NaN
endif
// Make sure trace is on graph
if (strlen(TraceInfo(graphName, traceName, 0)) < 1)
return NaN
endif
// So that we don't delete an annotation that has been placed
// on the graph outside of this function, filter the list
// of all annotations so we only process ones
// with names beginning with "highlight_tag_"
String listOfAnnotations = AnnotationList(graphName)
listOfAnnotations = ListMatch(listOfAnnotations, "highlight_tag_*", ";")
Variable numAnnotations = ItemsInList(listOfAnnotations, ";")
String currentAnnotationName, info
Variable n, attachedPoint
Variable removedATag
// Determine if there is already a tag on the trace at the
// specified point.
For (n=0; n<numAnnotations; n+=1)
currentAnnotationName = StringFromList(n, listOfAnnotations, ";")
info = AnnotationInfo(graphName, currentAnnotationName)
if (strlen(info) > 0)
// If this isn't a tag then ignore it.
if (cmpstr(StringByKey("TYPE", info, ":", ";"), "Tag") == 0)
// If this tag isn't attached to traceName, ignore it.
if (cmpstr(StringByKey("YWAVE", info, ":", ";"), traceName) == 0)
// If the tag isn't attached to point pointIndex, ignore it.
attachedPoint = NumberByKey("ATTACHX", info, ":", ";")
if (numtype(attachedPoint) == 0 && attachedPoint == pointIndex)
// Tag is already attached to the given point on the given
// graph and trace, so remove it.
Tag/W=$(graphName)/N=$(currentAnnotationName)/K
removedATag = 1
endif
endif
endif
endif
EndFor
// If we didn't just remove one or more tags, then we need to add a tag
// to the specified trace. If we did remove a tag, then just return.
if (!removedATag)
// Add a tag.
String newTagName = UniqueName("highlight_tag_", 14, 0, graphName)
Tag/W=$(graphName)/C/N=$(newTagName)/F=0/B=1/H={0,2,10}/X=0.00/Y=0.00/L=0/TL=0 $(traceName), pointIndex, "\\W519"
endif
return removedATag
End
//**
// Get a list of target windows.
//
// @TODO: This could be expanded so that
// child windows were also returned. As is, subwindows
// will not be affected.
//
// @return
// A string with a semicolon separated list of graph
// window names.
//*
Function/S GetTargetGraphList()
String targetGraphList = ""
targetGraphList = WinList("*", ";", "WIN:1") // All graph windows.
return targetGraphList
End
//**
// Window hook function that responds to clicking on a graph
// and then causes a data point to be highlighted.
// @param s
// An instance of the WMWinHookStruct structure.
// @return
// A non-zero value if this function handled the event or zero
// if it did not.
//*
Function HighlightDataPoint_Hook(s)
STRUCT WMWinHookStruct &s
Variable hookResult
// Only handle the event if the proper modifier key(s) were pressed.
if (s.eventCode == 5 && s.eventMod == HIGHLIGHT_CLICK_MODIFIERS)
// Determine the trace and wave that were clicked on and
// the point index where the user clicked.
String hitInfo = TraceFromPixel(s.mouseLoc.h, s.mouseLoc.v, "WINDOW:" + s.winName)
if (strlen(hitInfo) > 0)
String traceName = StringByKey("TRACE", hitInfo, ":", ";")
Variable hitPoint = NumberByKey("HITPOINT", hitInfo, ":", ";")
if (strlen(traceName) > 0 && numtype(hitPoint) == 0)
WAVE/Z targetWave = TraceNameToWaveRef(s.winName, traceName)
if (WaveExists(targetWave))
HighlightDataPoint(targetWave, hitPoint, s.winName)
hookResult = 1
endif
endif
endif
endif
return hookResult
End
//**
// Main utility function that is called to highlight (or remove the highlight from) a
// data point on a wave in a number of graph windows.
//
// @param targetWave
// A wave reference to the wave the user clicked on.
// @param pointIndex
// A variable containing the point value at which
// the tag should be added or removed.
// @param activeGraphName
// A string containing the name of the graph on which
// the user clicked. This graph will always have the tag
// toggled on or off.
// @param targetGraphList
// [OPTIONAL] A string containing a semicolon separated list
// of graphs which should have a tag added or removed if the
// specified wave is displayed on the graph. If this parameter
// is not specified all graph windows will be acted upon.
// *
Function HighlightDataPoint(targetWave, pointIndex, activeGraphName, [targetGraphList])
WAVE targetWave
Variable pointIndex
String activeGraphName
String targetGraphList
// If the parameter targetGraphList is not specified, then
// call a function to get target windows.
if (ParamIsDefault(targetGraphList))
targetGraphList = GetTargetGraphList()
endif
// Make sure that the active graph (the one the user used to
// trigger this function being called) is included in the list
// of graphs on which the highlighting of the point should be
// toggled.
if (WhichListItem(activeGraphName, targetGraphList, ";") < 0)
targetGraphList = AddListItem(activeGraphName, targetGraphList, ";", inf)
endif
Variable numGraphs = ItemsInList(targetGraphList, ";")
Variable n, traceIndex, numTraces
String currentGraphName
String thisWaveFullName
String targetWaveFullName
String traceList, currentTraceName
For (n=0; n<numGraphs; n+=1)
currentGraphName = StringFromList(n, targetGraphList, ";")
// Make sure this is actually a graph.
If (WinType(currentGraphName) != 1)
continue
endif
// Iterate through the traces on the graph to find
// if any of them are based on targetWave and if so then
// append or remove tags on the graph at the specified point.
// NOTE: This won't work as expected for traces
// that are XY pairs.
traceList = TraceNameList(currentGraphName, ";", 5) // Include normal graph traces and omit hidden traces
numTraces = ItemsInList(traceList, ";")
targetWaveFullName = GetWavesDataFolder(targetWave, 2)
thisWaveFullName = ""
traceIndex = 0
For (traceIndex = 0; traceIndex < numTraces; traceIndex +=1)
currentTraceName = StringFromList(traceIndex, traceList, ";")
WAVE/Z thisWave = TraceNameToWaveRef(currentGraphName, currentTraceName)
// If thisWave is NULL for any reason, skip it.
if (!WaveExists(thisWave))
continue
endif
// Determine if targetWave and thisWave are the same wave.
thisWaveFullName = GetWavesDataFolder(thisWave, 2)
if (cmpstr(thisWaveFullName, targetWaveFullName) == 0)
// Toggle the presence of tags for the given point on the specified graphs.
RemoveOrAddTagToTrace(currentGraphName, currentTraceName, pointIndex)
endif
EndFor
EndFor
End
//**
// Toggles the presence of a tag on the specified trace at the specified point.
//
// @param graphName
// A string containing the full name of the graph.
// @param traceName
// A string containing the name of the trace.
// @param pointIndex
// A variable containing the point value at which
// the tag should be added or removed.
//
// @return
// 1 if a tag was removed, 0 if it was added, or NaN if there was
// an error, such as an invalid graph or trace name.
//*
Function RemoveOrAddTagToTrace(graphName, traceName, pointIndex)
String graphName
String traceName
Variable pointIndex
// Make sure graph exists.
if (WinType(graphName) != 1)
return NaN
endif
// Make sure trace is on graph
if (strlen(TraceInfo(graphName, traceName, 0)) < 1)
return NaN
endif
// So that we don't delete an annotation that has been placed
// on the graph outside of this function, filter the list
// of all annotations so we only process ones
// with names beginning with "highlight_tag_"
String listOfAnnotations = AnnotationList(graphName)
listOfAnnotations = ListMatch(listOfAnnotations, "highlight_tag_*", ";")
Variable numAnnotations = ItemsInList(listOfAnnotations, ";")
String currentAnnotationName, info
Variable n, attachedPoint
Variable removedATag
// Determine if there is already a tag on the trace at the
// specified point.
For (n=0; n<numAnnotations; n+=1)
currentAnnotationName = StringFromList(n, listOfAnnotations, ";")
info = AnnotationInfo(graphName, currentAnnotationName)
if (strlen(info) > 0)
// If this isn't a tag then ignore it.
if (cmpstr(StringByKey("TYPE", info, ":", ";"), "Tag") == 0)
// If this tag isn't attached to traceName, ignore it.
if (cmpstr(StringByKey("YWAVE", info, ":", ";"), traceName) == 0)
// If the tag isn't attached to point pointIndex, ignore it.
attachedPoint = NumberByKey("ATTACHX", info, ":", ";")
if (numtype(attachedPoint) == 0 && attachedPoint == pointIndex)
// Tag is already attached to the given point on the given
// graph and trace, so remove it.
Tag/W=$(graphName)/N=$(currentAnnotationName)/K
removedATag = 1
endif
endif
endif
endif
EndFor
// If we didn't just remove one or more tags, then we need to add a tag
// to the specified trace. If we did remove a tag, then just return.
if (!removedATag)
// Add a tag.
String newTagName = UniqueName("highlight_tag_", 14, 0, graphName)
Tag/W=$(graphName)/C/N=$(newTagName)/F=0/B=1/H={0,2,10}/X=0.00/Y=0.00/L=0/TL=0 $(traceName), pointIndex, "\\W519"
endif
return removedATag
End
//**
// Get a list of target windows.
//
// @TODO: This could be expanded so that
// child windows were also returned. As is, subwindows
// will not be affected.
//
// @return
// A string with a semicolon separated list of graph
// window names.
//*
Function/S GetTargetGraphList()
String targetGraphList = ""
targetGraphList = WinList("*", ";", "WIN:1") // All graph windows.
return targetGraphList
End
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More