diff --git a/Generators/src/main/java/io/deephaven/plot/util/GeneratePyV2FigureAPI.java b/Generators/src/main/java/io/deephaven/plot/util/GeneratePyV2FigureAPI.java index 4987f35f26b..0c8607c20fa 100644 --- a/Generators/src/main/java/io/deephaven/plot/util/GeneratePyV2FigureAPI.java +++ b/Generators/src/main/java/io/deephaven/plot/util/GeneratePyV2FigureAPI.java @@ -879,6 +879,7 @@ private void generatePyFuncCallSequential(final StringBuilder sb, .append(INDENT) .append("j_figure = self.j_figure\n\n"); + boolean needsMskCheck = false; final Set> alreadyGenerated = new HashSet<>(); @@ -890,11 +891,18 @@ private void generatePyFuncCallSequential(final StringBuilder sb, final List argNames = pyArgNames(sigs, pyArgMap); for (String[] argName : argNames) { + needsMskCheck = needsMskCheck || Arrays.stream(argName).anyMatch("multi_series_key"::equals); final Pair e = new Pair<>(key, argName); items.add(e); } } + if (needsMskCheck) { + sb.append(INDENT) + .append(INDENT) + .append("multi_series_key_used = False\n\n"); + } + // sort from largest number of args to smallest number of args so that the most specific method is called items.sort((a, b) -> b.second.length - a.second.length); @@ -902,10 +910,17 @@ private void generatePyFuncCallSequential(final StringBuilder sb, final Key key = item.first; final String[] an = item.second; + final boolean mskUsed = Arrays.stream(an).anyMatch("multi_series_key"::equals); + validateArgNames(an, alreadyGenerated, signatures, pyArgMap); - final String[] quoted_an = Arrays.stream(an).map(s -> "\"" + s + "\"").toArray(String[]::new); + final String[] quotedAn = Arrays.stream(an).map(s -> "\"" + s + "\"").toArray(String[]::new); - if (quoted_an.length == 0) { + // prevent removal of multi_series_key until after it's been fully used + final String[] filteredQuotedAn = Arrays.stream(quotedAn) + .filter(s -> !s.equals("\"multi_series_key\"")) + .toArray(String[]::new); + + if (quotedAn.length == 0) { sb.append(INDENT) .append(INDENT) .append("if set()") @@ -914,7 +929,7 @@ private void generatePyFuncCallSequential(final StringBuilder sb, sb.append(INDENT) .append(INDENT) .append("if {") - .append(String.join(", ", quoted_an)) + .append(String.join(", ", quotedAn)) .append("}.issubset(non_null_args):\n"); } sb.append(INDENT) @@ -929,12 +944,31 @@ private void generatePyFuncCallSequential(final StringBuilder sb, .append(INDENT) .append(INDENT) .append("non_null_args = non_null_args.difference({") - .append(String.join(", ", quoted_an)) + .append(String.join(", ", filteredQuotedAn)) .append("})\n") .append(INDENT) .append(INDENT) .append(INDENT) - .append("f_called = True\n\n"); + .append("f_called = True\n"); + + if (mskUsed) { + sb.append(INDENT) + .append(INDENT) + .append(INDENT) + .append("multi_series_key_used = True\n"); + } + + sb.append("\n"); + } + + if (needsMskCheck) { + sb.append(INDENT) + .append(INDENT) + .append("if multi_series_key_used:\n") + .append(INDENT) + .append(INDENT) + .append(INDENT) + .append("non_null_args = non_null_args.difference({\"multi_series_key\"})\n\n"); } sb.append(INDENT) diff --git a/py/server/deephaven/plot/figure.py b/py/server/deephaven/plot/figure.py index 42a479d6ff0..bce3876e37b 100644 --- a/py/server/deephaven/plot/figure.py +++ b/py/server/deephaven/plot/figure.py @@ -443,6 +443,8 @@ def chart( f_called = False j_figure = self.j_figure + multi_series_key_used = False + if {"row", "col"}.issubset(non_null_args): j_figure = j_figure.chart(row, col) non_null_args = non_null_args.difference({"row", "col"}) @@ -455,8 +457,9 @@ def chart( if {"pie_label_format", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.piePercentLabelFormat(pie_label_format, multi_series_key) - non_null_args = non_null_args.difference({"pie_label_format", "multi_series_key"}) + non_null_args = non_null_args.difference({"pie_label_format"}) f_called = True + multi_series_key_used = True if {"index"}.issubset(non_null_args): j_figure = j_figure.chart(index) @@ -503,6 +506,9 @@ def chart( non_null_args = non_null_args.difference({"pie_label_format"}) f_called = True + if multi_series_key_used: + non_null_args = non_null_args.difference({"multi_series_key"}) + if not f_called or non_null_args: raise DHError(f"unsupported parameter combination: {non_null_args}") @@ -877,20 +883,25 @@ def line( f_called = False j_figure = self.j_figure + multi_series_key_used = False + if {"color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.lineColor(color, multi_series_key) - non_null_args = non_null_args.difference({"color", "multi_series_key"}) + non_null_args = non_null_args.difference({"color"}) f_called = True + multi_series_key_used = True if {"style", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.lineStyle(style, multi_series_key) - non_null_args = non_null_args.difference({"style", "multi_series_key"}) + non_null_args = non_null_args.difference({"style"}) f_called = True + multi_series_key_used = True if {"visible", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.linesVisible(visible, multi_series_key) - non_null_args = non_null_args.difference({"visible", "multi_series_key"}) + non_null_args = non_null_args.difference({"visible"}) f_called = True + multi_series_key_used = True if {"color"}.issubset(non_null_args): j_figure = j_figure.lineColor(color) @@ -907,6 +918,9 @@ def line( non_null_args = non_null_args.difference({"visible"}) f_called = True + if multi_series_key_used: + non_null_args = non_null_args.difference({"multi_series_key"}) + if not f_called or non_null_args: raise DHError(f"unsupported parameter combination: {non_null_args}") @@ -1512,30 +1526,37 @@ def point( f_called = False j_figure = self.j_figure + multi_series_key_used = False + if {"t", "category", "color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointColor(t, category, color, multi_series_key) - non_null_args = non_null_args.difference({"t", "category", "color", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "category", "color"}) f_called = True + multi_series_key_used = True if {"t", "category", "label", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointLabel(t, category, label, multi_series_key) - non_null_args = non_null_args.difference({"t", "category", "label", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "category", "label"}) f_called = True + multi_series_key_used = True if {"t", "category", "shape", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointShape(t, category, shape, multi_series_key) - non_null_args = non_null_args.difference({"t", "category", "shape", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "category", "shape"}) f_called = True + multi_series_key_used = True if {"t", "category", "size", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointSize(t, category, size, multi_series_key) - non_null_args = non_null_args.difference({"t", "category", "size", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "category", "size"}) f_called = True + multi_series_key_used = True if {"category", "color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointColor(category, color, multi_series_key) - non_null_args = non_null_args.difference({"category", "color", "multi_series_key"}) + non_null_args = non_null_args.difference({"category", "color"}) f_called = True + multi_series_key_used = True if {"t", "category", "color"}.issubset(non_null_args): j_figure = j_figure.pointColor(t, category, color) @@ -1544,13 +1565,15 @@ def point( if {"t", "color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointColor(t, color, multi_series_key) - non_null_args = non_null_args.difference({"t", "color", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "color"}) f_called = True + multi_series_key_used = True if {"category", "label", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointLabel(category, label, multi_series_key) - non_null_args = non_null_args.difference({"category", "label", "multi_series_key"}) + non_null_args = non_null_args.difference({"category", "label"}) f_called = True + multi_series_key_used = True if {"t", "category", "label"}.issubset(non_null_args): j_figure = j_figure.pointLabel(t, category, label) @@ -1559,13 +1582,15 @@ def point( if {"t", "label", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointLabel(t, label, multi_series_key) - non_null_args = non_null_args.difference({"t", "label", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "label"}) f_called = True + multi_series_key_used = True if {"category", "shape", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointShape(category, shape, multi_series_key) - non_null_args = non_null_args.difference({"category", "shape", "multi_series_key"}) + non_null_args = non_null_args.difference({"category", "shape"}) f_called = True + multi_series_key_used = True if {"t", "category", "shape"}.issubset(non_null_args): j_figure = j_figure.pointShape(t, category, shape) @@ -1574,13 +1599,15 @@ def point( if {"t", "shape", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointShape(t, shape, multi_series_key) - non_null_args = non_null_args.difference({"t", "shape", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "shape"}) f_called = True + multi_series_key_used = True if {"category", "size", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointSize(category, size, multi_series_key) - non_null_args = non_null_args.difference({"category", "size", "multi_series_key"}) + non_null_args = non_null_args.difference({"category", "size"}) f_called = True + multi_series_key_used = True if {"t", "category", "size"}.issubset(non_null_args): j_figure = j_figure.pointSize(t, category, size) @@ -1589,8 +1616,9 @@ def point( if {"t", "size", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointSize(t, size, multi_series_key) - non_null_args = non_null_args.difference({"t", "size", "multi_series_key"}) + non_null_args = non_null_args.difference({"t", "size"}) f_called = True + multi_series_key_used = True if {"category", "color"}.issubset(non_null_args): j_figure = j_figure.pointColor(category, color) @@ -1599,8 +1627,9 @@ def point( if {"color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointColor(color, multi_series_key) - non_null_args = non_null_args.difference({"color", "multi_series_key"}) + non_null_args = non_null_args.difference({"color"}) f_called = True + multi_series_key_used = True if {"t", "color"}.issubset(non_null_args): j_figure = j_figure.pointColor(t, color) @@ -1614,8 +1643,9 @@ def point( if {"label", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointLabel(label, multi_series_key) - non_null_args = non_null_args.difference({"label", "multi_series_key"}) + non_null_args = non_null_args.difference({"label"}) f_called = True + multi_series_key_used = True if {"t", "label"}.issubset(non_null_args): j_figure = j_figure.pointLabel(t, label) @@ -1624,8 +1654,9 @@ def point( if {"label_format", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointLabelFormat(label_format, multi_series_key) - non_null_args = non_null_args.difference({"label_format", "multi_series_key"}) + non_null_args = non_null_args.difference({"label_format"}) f_called = True + multi_series_key_used = True if {"category", "shape"}.issubset(non_null_args): j_figure = j_figure.pointShape(category, shape) @@ -1634,8 +1665,9 @@ def point( if {"shape", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointShape(shape, multi_series_key) - non_null_args = non_null_args.difference({"shape", "multi_series_key"}) + non_null_args = non_null_args.difference({"shape"}) f_called = True + multi_series_key_used = True if {"t", "shape"}.issubset(non_null_args): j_figure = j_figure.pointShape(t, shape) @@ -1649,8 +1681,9 @@ def point( if {"size", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointSize(size, multi_series_key) - non_null_args = non_null_args.difference({"size", "multi_series_key"}) + non_null_args = non_null_args.difference({"size"}) f_called = True + multi_series_key_used = True if {"t", "size"}.issubset(non_null_args): j_figure = j_figure.pointSize(t, size) @@ -1659,8 +1692,9 @@ def point( if {"visible", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.pointsVisible(visible, multi_series_key) - non_null_args = non_null_args.difference({"visible", "multi_series_key"}) + non_null_args = non_null_args.difference({"visible"}) f_called = True + multi_series_key_used = True if {"color"}.issubset(non_null_args): j_figure = j_figure.pointColor(color) @@ -1692,6 +1726,9 @@ def point( non_null_args = non_null_args.difference({"visible"}) f_called = True + if multi_series_key_used: + non_null_args = non_null_args.difference({"multi_series_key"}) + if not f_called or non_null_args: raise DHError(f"unsupported parameter combination: {non_null_args}") @@ -1826,40 +1863,49 @@ def series( f_called = False j_figure = self.j_figure + multi_series_key_used = False + if {"group", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.group(group, multi_series_key) - non_null_args = non_null_args.difference({"group", "multi_series_key"}) + non_null_args = non_null_args.difference({"group"}) f_called = True + multi_series_key_used = True if {"color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.seriesColor(color, multi_series_key) - non_null_args = non_null_args.difference({"color", "multi_series_key"}) + non_null_args = non_null_args.difference({"color"}) f_called = True + multi_series_key_used = True if {"tool_tip_pattern", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.toolTipPattern(tool_tip_pattern, multi_series_key) - non_null_args = non_null_args.difference({"tool_tip_pattern", "multi_series_key"}) + non_null_args = non_null_args.difference({"tool_tip_pattern"}) f_called = True + multi_series_key_used = True if {"x_tool_tip_pattern", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.xToolTipPattern(x_tool_tip_pattern, multi_series_key) - non_null_args = non_null_args.difference({"x_tool_tip_pattern", "multi_series_key"}) + non_null_args = non_null_args.difference({"x_tool_tip_pattern"}) f_called = True + multi_series_key_used = True if {"y_tool_tip_pattern", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.yToolTipPattern(y_tool_tip_pattern, multi_series_key) - non_null_args = non_null_args.difference({"y_tool_tip_pattern", "multi_series_key"}) + non_null_args = non_null_args.difference({"y_tool_tip_pattern"}) f_called = True + multi_series_key_used = True if {"error_bar_color", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.errorBarColor(error_bar_color, multi_series_key) - non_null_args = non_null_args.difference({"error_bar_color", "multi_series_key"}) + non_null_args = non_null_args.difference({"error_bar_color"}) f_called = True + multi_series_key_used = True if {"gradient_visible", "multi_series_key"}.issubset(non_null_args): j_figure = j_figure.gradientVisible(gradient_visible, multi_series_key) - non_null_args = non_null_args.difference({"gradient_visible", "multi_series_key"}) + non_null_args = non_null_args.difference({"gradient_visible"}) f_called = True + multi_series_key_used = True if {"axes"}.issubset(non_null_args): j_figure = j_figure.series(axes) @@ -1911,6 +1957,9 @@ def series( non_null_args = non_null_args.difference({"naming_function"}) f_called = True + if multi_series_key_used: + non_null_args = non_null_args.difference({"multi_series_key"}) + if not f_called or non_null_args: raise DHError(f"unsupported parameter combination: {non_null_args}")