1

I have been struggling with a problem for about a month. I have used ChatGPT-4o during this time, but it hasn't provided a satisfactory solution. The issue is as follows:

When a user clicks on a part of a curve, the segmented part should be draggable up and down, with the y-axis values updating accordingly as the mouse moves. However, the problem arises when I drag the segment curve: the axis does not match the curve. Specifically, while the y-axis moves with the curve, the values of the curve no longer align with the axis, and they change inconsistently.

Here is a part of my code. Note that "self.p1" or "self.ui.pw" is a PlotWidget object defined in a UI file. We added all curves and view boxes to this main object. The code is written in Python and uses PyQt5. I used three functions to define these parts:

ok_on_segments(self): This function adds all segments into the "nv" view box and then adds it to "self.ui.pw". on_curve_selected(self, curve_name): When the user clicks on a segment, this function is triggered. For each selected curve, I create a view box, set the exact range, enable dragging by mouse, fix all other curves, and add the new view box to the "self.ui.pw" object. Despite this setup, the y-axis values do not maintain alignment with the dragged curve segment.

Here is the relevant part of my code:
def ok_on_segments(self): #creat style for curves global colors, curve_to_vb_map, num_curves if self.split_btn_flag == 1: curve_name_dict = dict() curve_name_dict_temp = dict() self.p1.removeItem(self.curve_3) self.p2.removeItem(self.curve_1) colors[num_import % len(colors)] color = colors[0] width = 2
pen = pg.mkPen(color, width=width)

        #set data on a split curves
        for ind in range(self.segments_window.listWidget_complete.count()):
            list_item = self.segments_window.listWidget_complete.item(ind)
            if ind!=0:
                if list_item.flags() & Qt.ItemIsUserCheckable:
                    if list_item.checkState() == Qt.Checked:
                        if ind+1<=self.segments_window.listWidget_complete.count():
                            #convert s to min
                            x = []
                            try:
                                for item in self.data_dict[ind-1][f"step_{ind}"]["time"]:
                                    x.append(item/60)
                            except:
                                pass
                            
                            y = [x/self.sampleMass  for x in self.data_dict[ind-1][f"step_{ind}["dsc"]]
                            z = self.data_dict[ind-1][f"step_{ind}"]["temp"]
                            custom_pen,cl = self.apply_custom_style_DDSC(pen)
                            self.custom_pen_list_dsc.append(cl)
                            curve_name_dict[f'curve_{self.counter_name}'] = pg.PlotCurveItem(x, y,pen=custom_pen)
                            curve_name_dict[f'curve_{self.counter_name}'].setClickable(True)
                            num_import_ = 1
                            
                            curves_dict[num_curves] = {'curve_name':f'curve_{self.counter_name}' , 'curve_label':'DSC' }
                            num_curves = num_curves + 1
                            num_import_ =str(num_import)
                            self.textItem = pg.TextItem(text=f"{num_import_}.{ind}", color=color, anchor=(0, 0), border=pg.mkPen(color=color), fill=pg.mkBrush(None))
                            last_point = x[-1], y[-1]
                            self.textItem.setPos(last_point[0], last_point[1])
                            # Create a new view box and add items
                            self.p1.addItem(self.textItem)
                            self.counter_name += 1
     self.curve_name_dict = curve_name_dict
     nv = self.create_new_viewbox('dsc','l')
     for i in range(self.counter_name):
            try:
                nv.addItem(curve_name_dict[f'curve_{i}'])
                
            except:
                pass
      self.ui.pw.addItem(nv)
      nv.setZValue(1)
      self.curve_name_dict = curve_name_dict
      for curve_name, curve in self.curve_name_dict.items():
            curve.sigClicked.connect(partial(self.on_curve_selected, curve_name))

def on_curve_selected(self, curve_name): print(curve_name) for i in range(len(list(self.curve_name_dict.keys()))): if list(self.curve_name_dict.keys())[i]==curve_name: print(i) color_number = self.custom_pen_list_dsc[i] break y_min = 100 y_max = 0 for items in self.curve_name_dict.values(): if np.min(items.yData)<y_min: y_min = np.min(items.yData) if np.max(items.yData)>y_max: y_max = np.max(items.yData)

    dict_=self.curve_name_dict
    new_vbox = self.create_new_viewbox('DSC','l',color_number)
    if curve_name != self.current_name:
        curve = dict_[curve_name]
        new_vbox.addItem(dict_[curve_name])
        new_vbox.setZValue(1)
        self.ui.pw.addItem(new_vbox)
        self.ui.pw.setMouseEnabled(False) 
        new_vbox.setRange(yRange=(y_min, y_max))
        for k in  dict_.keys():
            if k!=curve_name:
                fixed_curve = FixedPlotDataItem(dict_[k].xData,dict_[k].yData)
                self.ui.pw.addItem(fixed_curve)
                
    self.current_viewbox = new_vbox 
    self.current_name = curve_name

def create_new_viewbox(self, label,pos,color='black'): new_viewbox = YAxisOnlyViewBox()

    # new_viewbox.setMouseMode(new_viewbox.RectMode)
    if pos == "l":
        self.p1.scene().addItem(new_viewbox)
        self.p1.showAxis('left')
        self.p1.getAxis('left').linkToView(new_viewbox)
        new_viewbox.setXLink(self.p1)
        self.configure_axis(self.p1.getAxis('left'), label,color)

class YAxisOnlyViewBox(pg.ViewBox): def init(self,*args, **kwargs): super().init(*args, **kwargs) # self.setMouseMode(self.RectMode) self.draggableItem = None self.dragOffset = None self.setMouseEnabled(x=False,y=True)

class FixedPlotDataItem(pg.PlotDataItem): def mouseDragEvent(self, ev): # Ignore mouse drag events to disable dragging pass

I tried adding one view box for each segment and then clearing the other view boxes. Additionally, I experimented with using PlotWidget items and subplots. I also tried using mouse events instead of sigClicked.

New contributor
negar is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.