Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong position for 3D Plot with more then one 3D plot in a Grid #413

Closed
Nick135 opened this issue Aug 30, 2023 · 7 comments · Fixed by #453
Closed

Wrong position for 3D Plot with more then one 3D plot in a Grid #413

Nick135 opened this issue Aug 30, 2023 · 7 comments · Fixed by #453

Comments

@Nick135
Copy link

Nick135 commented Aug 30, 2023

Description

Wrong position for 3D plot when more than one 3D plot in a grid. All 3D plots are on top of each other at the position of the last 3D plot. 2D plot works. Also if I mix 2D and 3D plots in a grid, all 2D plot are right and the 3D plots have the problem.

Repro steps

#r "nuget: Plotly.NET, 4.2.0"
#r "nuget: Plotly.NET.Interactive, 4.2.0"
#r "nuget: Plotly.NET.CSharp"


using Plotly.NET.CSharp;

var testData = new[]{1.0,1.1,2.0};

var y = testData.Select(s=>s*-1).ToList();
var s1 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*1.2).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 1 - 3D"
        );
var s2 = Chart.Point<double, double, string>(
            x: testData,
            y: y,
            Name: "Plot 2 - 2D"
        );
var s3 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*2.1).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 3 - 3D"
        );

Chart.Grid(new[]{s1,s2,s3}, 3,1).Show();

Expected behavior

Position of 3D plots should be right

Actual behavior

2D plot works. Also if I mix 2D and 3D plots in a grid, all 2D plot are right and the 3D plots have the problem.

8c82410a-48db-497a-870d-3ed65d2c2e33.zip

image

Related information

  • Operating system Windows 10
  • Branch Plotly.NET v4.2.0
  • .NET Runtime dotnet-sdk-7.0.400-win-x64
@kMutagene
Copy link
Member

kMutagene commented Aug 30, 2023

Hey @Nick135, thanks for reporting this. I can confirm this as a regression that seems to occur somewhere between 3.0 and 4.0. It seems to be specific for adding multiple 3D charts to a grid, as a complex example with many different trace types works (see https://plotly.net/chart-layout/multiple-charts.html#Using-subplots-of-different-trace-types-in-a-grid). Adding a second 3D chart breaks the grid in that example.

For now, a quick workaround would be falling back to pre 4.0 versions like this:

#r "nuget: Plotly.NET, 3.0.0"
#r "nuget: Plotly.NET.CSharp, 0.8.0"
#r "nuget: Plotly.NET.Interactive, 3.0.0"

image

@Nick135
Copy link
Author

Nick135 commented Aug 31, 2023

When I add WithXAxisStyle to both 3D Plots, I also get the problem with the v3.0.

#r "nuget: Plotly.NET, 3.0.0"
#r "nuget: Plotly.NET.CSharp, 0.8.0"
#r "nuget: Plotly.NET.Interactive, 3.0.0"


using Plotly.NET.CSharp;

var testData = new[]{1.0,1.1,2.0};

var y = testData.Select(s=>s*-1).ToList();
var s1 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*1.2).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 1 - 3D"
        )
        .WithXAxisStyle<string, string, string>(TitleText: "x1", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1))
        .WithYAxisStyle<string, string, string>(TitleText: "y1", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1));
var s2 = Chart.Point<double, double, string>(
            x: testData,
            y: y,
            Name: "Plot 2 - 2D"
        );
var s3 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*2.1).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 3 - 3D"
        )
        .WithXAxisStyle<string, string, string>(TitleText: "x2", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1))
        .WithYAxisStyle<string, string, string>(TitleText: "y2", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1));

Chart.Grid(new[]{s1,s2,s3}, 3,1).Show();

image

@bvenn
Copy link
Collaborator

bvenn commented Aug 31, 2023

Setting unique Axis ids seems to fix this behaviour.

Details
#r "nuget: Plotly.NET, 3.0.0"
#r "nuget: Plotly.NET.CSharp, 0.8.0"
#r "nuget: Plotly.NET.Interactive, 3.0.0"


using Plotly.NET.CSharp;

var testData = new[]{1.0,1.1,2.0};

var y = testData.Select(s=>s*-1).ToList();
var s1 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*1.2).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 1 - 3D"
        )
        .WithXAxisStyle<string, string, string>(TitleText: "x1", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1))
        .WithYAxisStyle<string, string, string>(TitleText: "y1", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(1));
var s2 = Chart.Point<double, double, string>(
            x: testData,
            y: y,
            Name: "Plot 2 - 2D"
        );
var s3 = Chart.Scatter3D<double, double, double, string>(
            x: testData,
            y: y,
            z: testData.Select(s=>s*2.1).ToList(),
            mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 3 - 3D"
        )
        .WithXAxisStyle<string, string, string>(TitleText: "x2", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(2))
        .WithYAxisStyle<string, string, string>(TitleText: "y2", Id: Plotly.NET.StyleParam.SubPlotId.Scene.NewScene(2));

Chart.Grid(new[]{s1,s2,s3}, 3,1).Show();

image

@Nick135
Copy link
Author

Nick135 commented Aug 31, 2023

@bvenn: It looks like it works, but when you see the second 3D Plot, the "TitleText" is not set.

image

@kMutagene
Copy link
Member

The root of this bug must be the assignment of new scene ids to the existing charts. The internal logic of Chart.Grid combines all charts and adds new unique axis, scene, ternary, etc. positions and ids. Here is the match case for 3D charts:

| TraceID.Cartesian3D ->
let scene =
layout.TryGetTypedValue<Scene> "scene"
|> Option.defaultValue (Scene.init ())
|> Scene.style (Domain = LayoutObjects.Domain.init (Row = rowIndex - 1, Column = colIndex - 1))
let sceneAnchor =
StyleParam.SubPlotId.Scene(i + 1)
gChart
|> GenericChart.mapTrace (fun t -> t :?> Trace3D |> Trace3DStyle.SetScene sceneAnchor :> Trace)
|> Chart.withScene (scene, (i + 1))

so setting a scene id other than 1 here will cause the issue of the contained axis styles not being added to the new scene, the same is true for all other chart types btw. This is by design, checking for any possible scene id (or axis id etc.) adds gigantic overhead to an already very complicated and hard to maintain function.

However, i cannot find striking differences in the code when e.g. comparing with the match case for Ternary traces;

| TraceID.Ternary ->
let ternary =
layout.TryGetTypedValue<Ternary> "ternary"
|> Option.defaultValue (Ternary.init ())
|> Ternary.style (
Domain = LayoutObjects.Domain.init (Row = rowIndex - 1, Column = colIndex - 1)
)
let ternaryAnchor =
StyleParam.SubPlotId.Ternary(i + 1)
gChart
|> GenericChart.mapTrace (fun t ->
t :?> TraceTernary |> TraceTernaryStyle.SetTernary ternaryAnchor :> Trace)
|> Chart.withTernary (ternary, (i + 1)))

which works fine:

#r "nuget: Plotly.NET, 4.2.0"
#r "nuget: Plotly.NET.Interactive, 4.2.0"
#r "nuget: Plotly.NET.CSharp"


using Plotly.NET.CSharp;

var testData = new[]{1.0,1.1,2.0};

var y = testData.Select(s=>s*-1).ToList();
var s1 = Chart.ScatterTernary<double, double, double, double, string>(
            A: testData,
            B: y,
            C: testData.Select(s=>s*1.2).ToList(),
            Mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 1 - Ternary"
        );
var s2 = Chart.Point<double, double, string>(
            x: testData,
            y: y,
            Name: "Plot 2 - 2D"
        );
var s3 = Chart.ScatterTernary<double, double, double, double, string>(
            A: testData,
            B: y,
            C: testData.Select(s=>s*1.2).ToList(),
            Mode: Plotly.NET.StyleParam.Mode.Lines_Markers,
            Name: "Plot 3 - Ternary"
        );

var g = Chart.Grid(new[]{s1,s2,s3}, 3,1);

g

image

@kMutagene
Copy link
Member

I found the core issue in the output at least. The row number for the scenes is incorrect, while it is correct in the ternary example:

with Chart.Scatter3D:

"scene":{
  "camera":{"projection":{"type":"perspective"}},
  "domain":{"row":2,"column":0} <-- row should be 0
},
"scene3":{
  "camera":{"projection":{"type":"perspective"}},
  "domain":{"row":2,"column":0}
}

with Chart.ScatterTernary:

"ternary":{
  "domain":{"row":0,"column":0}
},
"ternary3":{
  "domain":{"row":2,"column":0}
},

which is really weird because at least to my eyes the code looks identical.

@kMutagene
Copy link
Member

found the underlying issue, there are some fixes necessary that are deep in the low-level APIs, see #415 for details. This will be potentially backwards-incompatible and therefore be in v5.

kMutagene added a commit that referenced this issue May 24, 2024
- remove all existing axes/subplot layouts before adding a single new one each per respective grid cell
- add tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants