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.

Reply via email to