Hi Jacob,
You don't want the parenthesis after sigPositionChanged, the connection to
the signal was working just fine. The issue is a bug so that your new_i is
not updating properly (it's always zero), so nothing appears to happen.
The bug is in the logic for computing new_i (and selected_x_i). Originally,
the line was:
self.selected_x_i = np.argmin(np.abs(self.xcoords - self.crosshairx.value
()))
That assumes the x-axis coordinates/labels (eg, sample time values) are
stored in the array xcoords. The code then finds the array index holding
the x value closest to the position of the InfiniteLine. You are just using
the sample numbers as the x coordinate, which is fine, but what you have:
self.selected_x_i = np.argmin(np.abs(len(self.curvesData.get(0)) - self.
crosshairx.value()))
uses len(...), which is a single value (array length of 1), so the array
index is always zero. Change it to a range of the array index values:
self.selected_x_i = np.argmin(np.abs(np.arange(len(self.curvesData.get(0)))
- self.crosshairx.value()))
or, if you will always be indexing the x-axis values by sample number,
simply
self.selected_x_i = int(np.round(self.crosshairx.value()))
Other issues:
Add the InfiniteLine to the plotItem, not the scene.
Bounds for InfiniteLine should be len(data) - 1.
So code looks like:
#!/usr/bin/env python3
from PyQt5 import QtWidgets
import pyqtgraph as pg
import numpy as np
class CurveData():
def __init__(self):
self.data = np.random.rand(100)
def get(self, index):
return self.data
class TestPlot(pg.GraphicsLayoutWidget):
def __init__(self):
super().__init__()
self.curvesData = CurveData()
self.plotItem = self.addPlot()
self.plotItem.plot(self.curvesData.get(0))
self.cursorLine()
def cursorLine(self):
self.selected_x_i = 0
# Create the infinite line to select an x coordinate, connect to
its moved signal
self.crosshairx = pg.InfiniteLine(angle=90, movable=True, label=
"{:0.2f}".format(self.curvesData.get(0)[self.selected_x_i]))
self.crosshairx.sigPositionChanged.connect(self._crosshairx_changed)
self.crosshairx.setBounds(bounds=(0,len(self.curvesData.get(0)) - 1
))
# Keep track of index of currently selected x coordinate, so we can
avoid doing
# unnecessary updates when the infiniteline changes but the index
of the
# closest x/y data point is still the same
self.selected_x_i = int(np.round(self.crosshairx.value()))
self.plotItem.addItem(self.crosshairx)
def _crosshairx_changed(self):
new_i = int(np.round(self.crosshairx.value()))
if new_i != self.selected_x_i:
self.selected_x_i = new_i
self.crosshairx.label.setFormat("{:0.2f}".format(self.curvesData
.get(0)[self.selected_x_i]))
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
mainwindow = TestPlot()
mainwindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Patrick
On Tuesday, 18 December 2018 16:04:01 UTC+10:30, Jacob Bernard wrote:
>
> Hi Patrick,
>
> Thanks for taking the time to respond! Sorry I didn't reply sooner. I
> attempted to modify and implement your example, but I'm unable to get it to
> work properly:
>
> def cursorLine(self):
> self.selected_x_i = 0
> self.selected_x = str(self.curvesData.get(0)[self.selected_x_i])
>
> # Create the infinite line to select an x coordinate, connect to
> its moved signal
> self.crosshairx = pg.InfiniteLine(angle=90, movable=True,
> label=self.selected_x)
>
> self.crosshairx.sigPositionChanged().connect(self._crosshairx_changed)
>
> self.crosshairx.setBounds(bounds=(0,len(self.curvesData.get(0))))
>
> # Keep track of index of currently selected x coordinate, so we
> can avoid doing
> # unnecessary updates when the infiniteline changes but the index
> of the
> # closest x/y data point is still the same
> #self.selected_x_i = np.argmin(np.abs(len(self.curvesData.get(0))
> - self.crosshairx.value()))
>
> self.plotItem.scene().addItem(self.crosshairx)
>
>
> def _crosshairx_changed(self):
> new_i = np.argmin(np.abs(len(self.curvesData.get(0)) -
> self.crosshairx.value()))
> if new_i != self.selected_x_i:
> self.selected_x_i = new_i
> self.selected_x =
> str(self.curvesData.get(0)[self.selected_x_i])
> print(self.curvesData(0)[self.selected_x_i])
>
> Your emitting the setting of the label confused me a bit, but I understand
> the idea of the example in that you keep track of when the line is moved
> and thus change which X value you should be accessing. It seemed that there
> wasn't actually a connection between the line being moved and
> _crosshairx_changed() so I added the parenthesis after sigPositionChanged.
> This results in the error "TypeError: native Qt signal is not callable".
> Sorry about asking for help again, but I'm really not sure where to go from
> here.
>
> Kind Regards,
>
> Jacob
>
> On Friday, November 30, 2018 at 9:27:03 PM UTC-6, Patrick wrote:
>>
>> Hi,
>>
>> You can connect to signals emitted by the infiniteline when it is moved.
>> Example code snippet below:
>>
>>
>> # Assume plot data is stored in arrays of xcoords, yvalues
>> self.xcoords = np.linspace(0.1, 10, 10)
>> self.yvalues = np.log(self.xcoords)
>>
>>
>> # Create the infinite line to select an x coordinate, connect to its
>> moved signal
>> self.crosshairx = pg.InfiniteLine(angle=90, movable=True)
>> self.crosshairx.sigPositionChanged.connect(self._crosshairx_changed)
>>
>>
>> # Keep track of index of currently selected x coordinate, so we can avoid
>> doing
>> # unnecessary updates when the infiniteline changes but the index of the
>> # closest x/y data point is still the same
>> self.selected_x_i = np.argmin(np.abs(self.xcoords - self.crosshairx.value
>> ()))
>>
>>
>> # Slot to get y value of point closest to x value of the infinite line
>> def _crosshairx_changed(self):
>> new_i = np.argmin(np.abs(self.xcoords - self.crosshairx.value()))
>> if new_i != self.selected_x_i:
>> self.selected_x_i = new_i
>> # Do something interesting
>> print(self.yvalues[self.selected_x_i])
>>
>>
>> Patrick
>>
>> On Saturday, 1 December 2018 05:22:37 UTC+10:30, Jacob Bernard wrote:
>>>
>>> I have an infiniteline on my graph, and have figured out how to use
>>> value to get the value of the current axis:
>>>
>>> infline = pg.InfiniteLine(pos=1000, movable=True, label='{value:0.2fms}')
>>>
>>>
>>> However I would like to have my line vertically as it is now, but
>>> display the y values of my curves. Is this possible? I know that if I make
>>> the line horizontal it will give the y value, but I'd like for it to remain
>>> vertical.
>>>
>>>
>>>
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/b2d0956a-b11b-4bdf-b755-acc4ae68fc86%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.