pythonpython-3.xchartsplotlydisplay

Plotly display points on yaxis2 but do not on the yaxis1


I'm facing magic and I haven't found any counter-spells on the internet. The famous AIs didn't help me either.

When i display datas on the axis two it display but not on the axos one
img

If i change and put the points that are on the blue curve on the axis 2 and the one on the green to the axis one, it's the same problem:
img

Why the points do not display on the axis 1 Despite the annotations display well ?

My code :

def DisplayData(x_values, y_values_obj, y_range=None, y_tickformat=None, y_values_obj2=None, y_range2=None, y_tickformat2=None, title_x='x', title_y='y', title='', show=True, save_path='', dots=None, dots_color="green", dots2=None, dots2_color="green",y_categoryorder='trace'):
    def GetDots(dots,yaxis='y1',color='green'):
        positions = ['top center', 'bottom center']
        scatter_traces = []  # List to store scatter traces
        annotations = []  # List to store annotations
        dots_size = len(dots)

        for i, (name, point) in enumerate(dots.items()):
            if i % 10 == 0:
                print(f"{i*100/dots_size:.2f}", '%   ', end='\r')

            scatter_trace = go.Scatter(
                x=[point[0]],
                y=[point[1]],
                mode='markers',
                marker=dict(color=color),
                showlegend=False,
                yaxis=yaxis
            )
            scatter_traces.append(scatter_trace)
            if name == str(i):
                name = point[1]
                
            # Add annotation for point name
            shift = (-1 if i % 2 == 0 else 1)
            annotation = go.layout.Annotation(
                x=point[0],
                y=point[1],
                text=name,
                showarrow=False,
                bgcolor='white',
                font=dict(color='black', size=12),
                xshift=10 * shift,
                yshift=20 * shift,
                yref=yaxis
            )
            annotations.append(annotation)
        return scatter_traces, annotations
    
    # Create DataFrame for line plot
    df = pd.DataFrame({'x': x_values})

    if isinstance(y_values_obj, list):
        for i, y_values in enumerate(y_values_obj):
            df[f'y_{i+1}'] = y_values
        y_names = [f'y_{i+1}' for i in range(len(y_values_obj))]
    elif isinstance(y_values_obj, dict):
        for name, y_values in y_values_obj.items():
            df[name] = y_values
        y_names = list(y_values_obj.keys())
    else:
        raise Exception('y_values_obj must be a list or a dict but it\'s a ',type(y_values_obj))


    # Create line plot
    fig = px.line(df, x='x', y=y_names, title=title) #, markers=True
    
    fig.update_layout(annotations=[])
    if dots:
        scatter_traces, annotations = GetDots(dots,yaxis='y',color=dots_color)
        print(scatter_traces)
        fig.add_traces(scatter_traces) # Add all scatter traces to fig at once
        for annotation in annotations:
            fig.add_annotation(annotation)
    if dots2:
        scatter_traces, annotations = GetDots(dots2,yaxis='y2',color=dots2_color)
        print(scatter_traces)
        fig.add_traces(scatter_traces) # Add all scatter traces to fig at once
        for annotation in annotations:
            fig.add_annotation(annotation)

    
    # Add right-aligned y_values_obj2
    if y_values_obj2:
        if isinstance(y_values_obj2, list):
            for i, y_values in enumerate(y_values_obj2):
                y_name = f'y_{i+1+len(y_names)}'
                fig.add_trace(go.Scatter(x=x_values, y=y_values, mode='lines', name=y_name, yaxis='y2'))
                y_names.append(y_name)
        elif isinstance(y_values_obj2, dict):
            for name, y_values in y_values_obj2.items():
                fig.add_trace(go.Scatter(x=x_values, y=y_values, mode='lines', name=name, yaxis='y2'))
                y_names.append(name)

    # Update layout
    fig.update_layout(xaxis=dict(title=dict(text=title_x)), 
                      yaxis=dict(title=dict(text=title_y), categoryorder=y_categoryorder, range=y_range, tickformat=y_tickformat),
                      yaxis2=dict(side='right', range=y_range2, tickformat=y_tickformat2))


    # Save the graph
    if save_path:
        #fig.write_image(save_path, width=800, height=600)
        pass

    # Display the graph
    if show:
        fig.show()

Solution

  • My function was too bad so i started from 0 again and here the result without troubles :

    def DisplayData(x_values, y_values_obj, y_range=None, y_tickformat=None, y_values_obj2=None, y_range2=None, y_tickformat2=None, title_x='x', title_y='y',title_y2='y2', title='', show=True, save_path='',annotations=True, dots=None, dots_names=None, dots_color=None, dots2=None, dots2_names=None, dots2_color=None,y_categoryorder='trace',axis_type="linear", axis_type2="linear", x_type="linear"):
        def AddCurve(fig, x_values,y_obj,mode='lines',yaxis='y',marker=None,name=None, showlegend=True, color=None):
            if y_obj==None:
                pass
            elif isinstance(y_obj, list):
                if isinstance(y_obj[0],list):
                    for i, y_values in enumerate(y_obj):
                        fig.add_trace(go.Scatter(x=x_values, y=y_values, mode=mode, name=name if name!=None else f'y_{i}', yaxis=yaxis, showlegend=showlegend, marker=dict(color=color),))
                else:
                    fig.add_trace(go.Scatter(x=x_values, y=y_obj, mode=mode, name=name if name!=None else 'y_', yaxis=yaxis, showlegend=showlegend, marker=dict(color=color),))
            elif isinstance(y_obj, dict):
                for dic_name, y_values in y_obj.items():
                    fig.add_trace(go.Scatter(x=x_values, y=y_values, mode=mode, name=name if name!=None else dic_name, yaxis=yaxis, showlegend=showlegend, marker=dict(color=color),))
            else:
                raise Exception('y_obj must be a list or a dict but it\'s a ',type(y_obj))
        
        def AddAnotations(fig, x_values, y_values, yaxis='y', names=None):
            for i in range(len(x_values)):
                shift = (-1 if i % 2 == 0 else 1)
                fig.add_annotation( go.layout.Annotation(
                    x=x_values[i],
                    y=y_values[i],
                    text=y_values[i] if names==None or names[i]==None else names[i],
                    xshift=10 * shift,
                    yshift=20 * shift,
                    yref=yaxis,
                    showarrow=False,
                    bgcolor='white',
                ))
    
        fig = go.Figure()
        AddCurve(fig, x_values, y_values_obj, mode='lines+markers', yaxis='y')
        AddCurve(fig, x_values, y_values_obj2, mode='lines', yaxis='y2')
        if dots:
            AddCurve(fig, dots[0], dots[1], mode='markers', yaxis='y', showlegend=False, color=dots_color)
            if annotations:
                AddAnotations(fig, dots[0], dots[1], yaxis='y', names=dots_names)
        if dots2:
            AddCurve(fig, dots2[0], dots2[1], mode='markers', yaxis='y2', showlegend=False, color=dots2_color)
            if annotations:
                AddAnotations(fig, dots2[0], dots2[1], yaxis='y2', names=dots2_names)
    
        fig.update_layout(
            yaxis=dict(title=title_y, range=y_range, tickformat=y_tickformat, type=axis_type),
            yaxis2=dict( title=title_y2, overlaying='y', side='right', range=y_range2, tickformat=y_tickformat2, type=axis_type2),
            xaxis=dict(title=title_x, type=x_type),
            title=title,
        )
    
        if show:
            fig.show()