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

Add chart series support for point shapes and sizes #3246

Merged
merged 5 commits into from
Jan 30, 2023

Conversation

mofojed
Copy link
Member

@mofojed mofojed commented Dec 28, 2022

from deephaven import empty_table
from deephaven.plot import Figure
import math

math_funcs = ["sin", "cos"]
shapes = ["SQUARE", "CIRCLE", "UP_TRIANGLE", "DOWN_TRIANGLE", "RIGHT_TRIANGLE", "LEFT_TRIANGLE", "DIAMOND"]
size = 50
# Unsupported shapes: ["ELLIPSE", "HORIZONTAL_RECTANGLE", "VERTICAL_RECTANGLE"]

# Create a generic table that has enough columns to display all the shapes
# Re-uses some of the funcs
t = empty_table(size).update([f"name=`` + shapes[(int)Math.floor(i / Math.ceil(size / {len(shapes)}))]", "x=i*0.1"])
for i in range(len(shapes)):
    t = t.update([f"y{i}=Math.{math_funcs[i % len(math_funcs)]}(x+{math.floor(i / len(math_funcs))})"])

# Create a figure showing all the different shapes one for each series
p = Figure()
for i in range(len(shapes)):
    p = p.plot_xy(series_name=shapes[i], t=t, x="x", y=f"y{i}").point(shape=shapes[i], size=len(shapes) - i, visible=True)
p = p.show();

# Create a plot by figure
p2 = Figure().plot_xy(series_name="Multi", t=t, by=["name"], x="x", y="y1").line(visible=True)
for i in range(len(shapes)):
    p2 = p2.point(shape=shapes[i], multi_series_key=[shapes[i]], size=len(shapes) - i, visible=True)
p2 = p2.show()
  • Used the following code in Groovy to test with plotBy as well:
names = ["A", "B", "C", "D", "E"]
mathFuncs = ["sin", "cos"]
shapes = ["SQUARE", "CIRCLE", "UP_TRIANGLE", "DOWN_TRIANGLE", "RIGHT_TRIANGLE", "LEFT_TRIANGLE", "DIAMOND"]
// Unsupported shapes: ["ELLIPSE", "HORIZONTAL_RECTANGLE", "VERTICAL_RECTANGLE"]

// Create a generic table that has enough columns to display all the shapes
// Re-uses some of the funcs
t = emptyTable(50).update("name=shapes[i % 7]", "x=i")
for (i = 0; i < shapes.size; i += 1) {
    t = t.update("y" + i + "=Math." + mathFuncs[i % mathFuncs.size] + "(x+" + Math.floor(i / mathFuncs.size) + ")")
}

// # Generate the table and figure based on the shapes created
p = figure()
for (i = 0; i < shapes.size; i += 1) {
    p = p.plot(shapes[i], t, "x", "y" + i).pointShape(shapes[i]).pointSize(shapes.size - i).pointsVisible(true)
}
p = p.show()

p2 = plotBy("plotBy", t, "x", "y1", ["name"] as String[]).pointsVisible(true)
for (i = 0; i < shapes.size; i += 1) {
  p2 = p2.pointShape(shapes[i], [shapes[i]] as String[]).linesVisible(true)
}
p2 = p2.show()

image

image

Copy link
Member

@rcaudy rcaudy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about MultiSeries?

@mofojed
Copy link
Member Author

mofojed commented Jan 11, 2023

MultiSeries does set the point shapes (line 465, line 502) but I'm not sure how to test it. I think I need plot_by functionality which hasn't been plumbed through yet. Or do you know of a way to trigger it?

Copy link
Member

@rcaudy rcaudy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge like this, but we should figure out about multi-series before merging.

@rcaudy
Copy link
Member

rcaudy commented Jan 12, 2023

MultiSeries does set the point shapes (line 465, line 502) but I'm not sure how to test it. I think I need plot_by functionality which hasn't been plumbed through yet. Or do you know of a way to trigger it?

It looks to me like plotBy, catPlotBy, and ohlcPlotBy will make a MultiSeries.

@mofojed
Copy link
Member Author

mofojed commented Jan 12, 2023

plot_by doesn't seem to be available in python, so I converted the code to Groovy and add a plotBy to get a multi-series. It looks like the point shapes are appearing as expected (see the screenshot and code snippet in my original comment).

@mofojed mofojed requested a review from rcaudy January 12, 2023 13:37
@mofojed
Copy link
Member Author

mofojed commented Jan 12, 2023

@niloc132 pointed out there is actually a plot-by-key in python: https://deephaven.io/core/docs/reference/cheat-sheets/cheat-sheet/#plot-by-some-key

I tried to map the same groovy snippet above to using plotBy in Python, but server is throwing an NPE:

from deephaven import empty_table
from deephaven.plot import Figure
import math

math_funcs = ["sin", "cos"]
shapes = ["SQUARE", "CIRCLE", "UP_TRIANGLE", "DOWN_TRIANGLE", "RIGHT_TRIANGLE", "LEFT_TRIANGLE", "DIAMOND"]
# Unsupported shapes: ["ELLIPSE", "HORIZONTAL_RECTANGLE", "VERTICAL_RECTANGLE"]

# Create a generic table that has enough columns to display all the shapes
# Re-uses some of the funcs
t = empty_table(50).update([f"name=shapes[i % 5]", "x=i*0.1"])
for i in range(len(shapes)):
    t = t.update([f"y{i}=Math.{math_funcs[i % len(math_funcs)]}(x+{math.floor(i / len(math_funcs))})"])

# Generate the table and figure based on the shapes created
p = Figure()
for i in range(len(shapes)):
    p = p.plot_xy(series_name=shapes[i], t=t, x="x", y=f"y{i}").point(shape=shapes[i], size=len(shapes) - i, visible=True)

p = p.show();

p2 = Figure().plot_xy(series_name="Multi", t=t, x="x", y="y1", by=["name"]).point(visible=True)
for i in range(len(shapes)):
    p2 = p2.point(shape=shapes[i], multi_series_key=[shapes[i]])

p2 = p2.show()

Throws:

heduler-Concurrent-1 | i.d.s.s.SessionState      | Internal Error '2d7baeac-6803-4c68-bef1-e1b31c0be75d' java.lang.NullPointerException: null
        at io.deephaven.extensions.barrage.util.ExportUtil.buildTableCreationResponse(ExportUtil.java:20)
        at io.deephaven.extensions.barrage.util.ExportUtil.buildTableCreationResponse(ExportUtil.java:13)
        at io.deephaven.server.partitionedtable.PartitionedTableServiceGrpcImpl.lambda$getTable$8(PartitionedTableServiceGrpcImpl.java:166)
        at io.deephaven.server.session.SessionState$ExportObject.doExport(SessionState.java:886)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at io.deephaven.server.runner.DeephavenApiServerModule$ThreadFactory.lambda$newThread$0(DeephavenApiServerModule.java:165)
        at java.lang.Thread.run(Thread.java:829)

Not sure what I'm doing wrong there, but I tried a different example in python and it worked:

from deephaven.plot import Figure

table_3_keys = static_source_1.head(2000).where("String1 in `A`, `B`, `C`")\
    .sort("Int1").update(["New_Row = i", "Y = Int1 * (String1 = `A` ? 2 : String1 = `B` ? 0.5 : 1.0)"])
p = Figure().plot_xy(series_name="partitioned", t=table_3_keys, by=["String1"], x="New_Row", y="Y").point(shape="SQUARE", visible=True, multi_series_key=["A"]).point(shape="DIAMOND", visible=True, multi_series_key=["B"]).point(shape="UP_TRIANGLE", visible=True, multi_series_key=["C"]).show()

@mofojed
Copy link
Member Author

mofojed commented Jan 12, 2023

Figured out what the issue was in my snippet above. The problem was on this line:

t = empty_table(50).update([f"name=shapes[i % 5]", "x=i*0.1"])

This was creating a table where name was of type PyObject. I needed to change it to a native String, I did it with string concatenation:

t = empty_table(50).update([f"name=`` + shapes[i % 5]", "x=i"])

Not sure if there's anything we can do about that, pretty annoying that it can't handle the first syntax correctly.

rcaudy
rcaudy previously approved these changes Jan 12, 2023
@mofojed mofojed merged commit c9beb0b into deephaven:main Jan 30, 2023
@mofojed mofojed deleted the figure-point-shapes branch January 30, 2023 16:23
@github-actions github-actions bot locked and limited conversation to collaborators Jan 30, 2023
@deephaven-internal
Copy link
Contributor

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants