From df4d09212db7a2301a69e4739da8e7167dccefb5 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Wed, 19 Jun 2024 12:49:15 -0700 Subject: [PATCH 01/20] changes --- demo/native_plots/bar_plot_demo.py | 18 +- demo/native_plots/line_plot_demo.py | 13 +- demo/native_plots/scatter_plot_demo.py | 7 +- gradio/components/bar_plot.py | 5 +- gradio/components/line_plot.py | 5 +- gradio/components/scatter_plot.py | 5 +- js/plot/package.json | 4 +- js/plot/shared/Plot.svelte | 228 ++---------------- js/plot/shared/plot_types/AltairPlot.svelte | 137 +++++++++++ js/plot/shared/plot_types/BokehPlot.svelte | 81 +++++++ .../shared/plot_types/MatplotlibPlot.svelte | 24 ++ js/plot/shared/plot_types/PlotlyPlot.svelte | 35 +++ js/plot/shared/plot_types/altair_utils.ts | 55 +++++ js/plot/shared/utils.ts | 40 --- pnpm-lock.yaml | 46 +--- requirements.txt | 2 +- 16 files changed, 391 insertions(+), 314 deletions(-) create mode 100644 js/plot/shared/plot_types/AltairPlot.svelte create mode 100644 js/plot/shared/plot_types/BokehPlot.svelte create mode 100644 js/plot/shared/plot_types/MatplotlibPlot.svelte create mode 100644 js/plot/shared/plot_types/PlotlyPlot.svelte create mode 100644 js/plot/shared/plot_types/altair_utils.ts delete mode 100644 js/plot/shared/utils.ts diff --git a/demo/native_plots/bar_plot_demo.py b/demo/native_plots/bar_plot_demo.py index a4432e121bcbc..fd4e587cb2114 100644 --- a/demo/native_plots/bar_plot_demo.py +++ b/demo/native_plots/bar_plot_demo.py @@ -98,14 +98,14 @@ def bar_plot_fn(display): with gr.Blocks() as bar_plot: - with gr.Row(): - with gr.Column(): - display = gr.Dropdown( - choices=["simple", "stacked", "grouped", "simple-horizontal", "stacked-horizontal", "grouped-horizontal"], - value="simple", - label="Type of Bar Plot" - ) - with gr.Column(): - plot = gr.BarPlot(show_label=False, show_actions_button=True) + display = gr.Dropdown( + choices=["simple", "stacked", "grouped", "simple-horizontal", "stacked-horizontal", "grouped-horizontal"], + value="simple", + label="Type of Bar Plot" + ) + plot = gr.BarPlot(show_label=False, show_actions_button=True) display.change(bar_plot_fn, inputs=display, outputs=plot) bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot) + +if __name__ == "__main__": + bar_plot.launch() \ No newline at end of file diff --git a/demo/native_plots/line_plot_demo.py b/demo/native_plots/line_plot_demo.py index 49b87d8db2f4a..1c88b1fe5bab6 100644 --- a/demo/native_plots/line_plot_demo.py +++ b/demo/native_plots/line_plot_demo.py @@ -78,14 +78,11 @@ def line_plot_fn(dataset): with gr.Blocks() as line_plot: - with gr.Row(): - with gr.Column(): - dataset = gr.Dropdown( - choices=["stocks", "climate", "seattle_weather", "gapminder"], - value="stocks", - ) - with gr.Column(): - plot = gr.LinePlot() + dataset = gr.Dropdown( + choices=["stocks", "climate", "seattle_weather", "gapminder"], + value="stocks", + ) + plot = gr.LinePlot() dataset.change(line_plot_fn, inputs=dataset, outputs=plot) line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot) diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py index 3ae129ea9d3a7..6594cf1491892 100644 --- a/demo/native_plots/scatter_plot_demo.py +++ b/demo/native_plots/scatter_plot_demo.py @@ -35,11 +35,8 @@ def scatter_plot_fn(dataset): with gr.Blocks() as scatter_plot: - with gr.Row(): - with gr.Column(): - dataset = gr.Dropdown(choices=["cars", "iris"], value="cars") - with gr.Column(): - plot = gr.ScatterPlot(show_label=False) + dataset = gr.Dropdown(choices=["cars", "iris"], value="cars") + plot = gr.ScatterPlot(show_label=False) dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot) scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot) diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py index 08da7225d2b5c..e23b6e1847fb9 100644 --- a/gradio/components/bar_plot.py +++ b/gradio/components/bar_plot.py @@ -126,6 +126,8 @@ def __init__( self.height = height self.sort = sort self.show_actions_button = show_actions_button + if label is None and show_label is None: + show_label = False super().__init__( value=value, label=label, @@ -234,6 +236,7 @@ def create_plot( properties["width"] = width if color: + color_legend_position = color_legend_position or "bottom" domain = value[color].unique().tolist() range_ = list(range(len(domain))) encodings["color"] = { @@ -241,7 +244,7 @@ def create_plot( "type": "nominal", "scale": {"domain": domain, "range": range_}, "legend": AltairPlot.create_legend( - position=color_legend_position, title=color_legend_title or color + position=color_legend_position, title=color_legend_title ), } diff --git a/gradio/components/line_plot.py b/gradio/components/line_plot.py index 31dae8567a96b..138b87849b212 100644 --- a/gradio/components/line_plot.py +++ b/gradio/components/line_plot.py @@ -139,6 +139,8 @@ def __init__( self.width = width self.height = height self.show_actions_button = show_actions_button + if label is None and show_label is None: + show_label = False super().__init__( value=value, label=label, @@ -234,6 +236,7 @@ def create_plot( properties["width"] = width if color: + color_legend_position = color_legend_position or "bottom" domain = value[color].unique().tolist() range_ = list(range(len(domain))) encodings["color"] = { @@ -241,7 +244,7 @@ def create_plot( "type": "nominal", "scale": {"domain": domain, "range": range_}, "legend": AltairPlot.create_legend( - position=color_legend_position, title=color_legend_title or color + position=color_legend_position, title=color_legend_title ), } diff --git a/gradio/components/scatter_plot.py b/gradio/components/scatter_plot.py index 581809468c0a3..a9c4cf78ab051 100644 --- a/gradio/components/scatter_plot.py +++ b/gradio/components/scatter_plot.py @@ -156,6 +156,8 @@ def __init__( self.x_lim = x_lim self.y_lim = y_lim self.show_actions_button = show_actions_button + if label is None and show_label is None: + show_label = False super().__init__( value=value, label=label, @@ -273,11 +275,12 @@ def create_plot( range_ = list(range(len(domain))) type_ = "nominal" + color_legend_position = color_legend_position or "bottom" encodings["color"] = { "field": color, "type": type_, "legend": AltairPlot.create_legend( - position=color_legend_position, title=color_legend_title or color + position=color_legend_position, title=color_legend_title ), "scale": {"domain": domain, "range": range_}, } diff --git a/js/plot/package.json b/js/plot/package.json index d0075a968cd70..2eee4483e078b 100644 --- a/js/plot/package.json +++ b/js/plot/package.json @@ -14,8 +14,8 @@ "@gradio/utils": "workspace:^", "@rollup/plugin-json": "^6.0.0", "plotly.js-dist-min": "^2.10.1", - "svelte-vega": "^2.0.0", - "vega": "^5.22.1", + "vega": "^5.23.0", + "vega-embed": "^6.25.0", "vega-lite": "^5.12.0" }, "devDependencies": { diff --git a/js/plot/shared/Plot.svelte b/js/plot/shared/Plot.svelte index c8213000e3d09..dffdbf9a0fa31 100644 --- a/js/plot/shared/Plot.svelte +++ b/js/plot/shared/Plot.svelte @@ -1,235 +1,39 @@ {#if value && type == "plotly"} -
+ {:else if type == "bokeh"} -
+ {:else if type == "altair"} -
- - {#if caption} -
- {caption} -
- {/if} -
+ {:else if type == "matplotlib"} -
- {`${value.chart} -
+ {:else} {/if} - - diff --git a/js/plot/shared/plot_types/AltairPlot.svelte b/js/plot/shared/plot_types/AltairPlot.svelte new file mode 100644 index 0000000000000..7a08d1ef46744 --- /dev/null +++ b/js/plot/shared/plot_types/AltairPlot.svelte @@ -0,0 +1,137 @@ + + +
+
+ {#if caption} +
+ {caption} +
+ {/if} +
+ + diff --git a/js/plot/shared/plot_types/BokehPlot.svelte b/js/plot/shared/plot_types/BokehPlot.svelte new file mode 100644 index 0000000000000..c05d721939f15 --- /dev/null +++ b/js/plot/shared/plot_types/BokehPlot.svelte @@ -0,0 +1,81 @@ + + +
+ + diff --git a/js/plot/shared/plot_types/MatplotlibPlot.svelte b/js/plot/shared/plot_types/MatplotlibPlot.svelte new file mode 100644 index 0000000000000..861f1c5999ffa --- /dev/null +++ b/js/plot/shared/plot_types/MatplotlibPlot.svelte @@ -0,0 +1,24 @@ + + +
+ {`${value.chart} +
+ + diff --git a/js/plot/shared/plot_types/PlotlyPlot.svelte b/js/plot/shared/plot_types/PlotlyPlot.svelte new file mode 100644 index 0000000000000..f2a1069936e6a --- /dev/null +++ b/js/plot/shared/plot_types/PlotlyPlot.svelte @@ -0,0 +1,35 @@ + + +
diff --git a/js/plot/shared/plot_types/altair_utils.ts b/js/plot/shared/plot_types/altair_utils.ts new file mode 100644 index 0000000000000..85ba1bc6d24bc --- /dev/null +++ b/js/plot/shared/plot_types/altair_utils.ts @@ -0,0 +1,55 @@ +import type { Config as VegaConfig } from "vega"; + +export function create_config(computed_style: CSSStyleDeclaration): VegaConfig { + let bodyTextColor = computed_style.getPropertyValue("--body-text-color"); + let borderColorPrimary = computed_style.getPropertyValue( + "--border-color-primary" + ); + let fontFamily = computed_style.fontFamily; + let titleWeight = computed_style.getPropertyValue( + "--block-title-text-weight" + ) as "bold" | "normal" | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900; + const fontToPxVal = (font: string) => { + return font.endsWith("px") ? parseFloat(font.slice(0, -2)) : 12; + }; + let textSizeMd = fontToPxVal(computed_style.getPropertyValue("--text-md")); + let textSizeSm = fontToPxVal(computed_style.getPropertyValue("--text-sm")); + return { + autosize: { type: "fit", contains: "padding" }, + axis: { + labelFont: fontFamily, + labelColor: bodyTextColor, + titleFont: fontFamily, + titleColor: bodyTextColor, + tickColor: borderColorPrimary, + labelFontSize: textSizeSm, + gridColor: borderColorPrimary, + titleFontWeight: "normal", + titleFontSize: textSizeSm, + labelFontWeight: "normal", + domain: false, + labelAngle: 0 + }, + legend: { + labelColor: bodyTextColor, + labelFont: fontFamily, + titleColor: bodyTextColor, + titleFont: fontFamily, + titleFontWeight: "normal", + titleFontSize: textSizeSm, + labelFontWeight: "normal", + offset: 2 + }, + title: { + color: bodyTextColor, + font: fontFamily, + fontSize: textSizeMd, + fontWeight: titleWeight, + anchor: "middle" + }, + view: { + stroke: borderColorPrimary + }, + header: { labelFont: computed_style.fontFamily, labelColor: bodyTextColor } + }; +} diff --git a/js/plot/shared/utils.ts b/js/plot/shared/utils.ts deleted file mode 100644 index c1c49b27c3034..0000000000000 --- a/js/plot/shared/utils.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { Config as VegaConfig } from "vega"; - -export const dark = "#e2e8f0"; -export const light = "#111827"; - -export function create_config(darkmode: boolean): VegaConfig { - return { - axis: { - labelFont: "sans-serif", - labelColor: darkmode ? dark : light, - titleFont: "sans-serif", - titleColor: darkmode ? dark : light, - tickColor: "#aaa", - gridColor: "#aaa", - titleFontWeight: "normal", - labelFontWeight: "normal" - }, - legend: { - labelColor: darkmode ? dark : light, - labelFont: "sans-serif", - titleColor: darkmode ? dark : light, - titleFont: "sans-serif", - titleFontWeight: "normal", - labelFontWeight: "normal" - }, - title: { - color: darkmode ? dark : light, - font: "sans-serif", - fontWeight: "normal", - anchor: "middle" - } - }; -} - -export function bar_plot_header_encoding(darkmode: boolean): { - labelFont: string; - labelColor: string; -} { - return { labelFont: "sans-serif", labelColor: darkmode ? dark : light }; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fca33ec6a03e6..29e0df9064a0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1564,12 +1564,12 @@ importers: plotly.js-dist-min: specifier: ^2.10.1 version: 2.10.1 - svelte-vega: - specifier: ^2.0.0 - version: 2.0.0(svelte@4.2.15)(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0) vega: - specifier: ^5.22.1 + specifier: ^5.23.0 version: 5.23.0 + vega-embed: + specifier: ^6.25.0 + version: 6.25.0(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0) vega-lite: specifier: ^5.12.0 version: 5.12.0(vega@5.23.0) @@ -8757,13 +8757,6 @@ packages: svelte-range-slider-pips@2.0.1: resolution: {integrity: sha512-sCHvcTgi0ZYE4c/mwSsdALRsfuqEmpwTsSUdL+PUrumZ8u2gv1GKwZ3GohcAcTB6gfmqRBkyn6ujRXrOIga1gw==} - svelte-vega@2.0.0: - resolution: {integrity: sha512-WnJM+hQNw15VAUtwT6oteog3+0KRw8i8K02gAB4VLM0RYs2NXxBZ1q/BdOvkl1XVnZytRVlLr1HQgxeZs7QwUA==} - peerDependencies: - svelte: ^3.54.0 - vega: '*' - vega-lite: '*' - svelte2tsx@0.7.7: resolution: {integrity: sha512-HAIxtk5TUHXvCRKApKfxoh1BGT85S/17lS3DvbfxRKFd+Ghr5YScqBvd+sU+p7vJFw48LNkzdFk+ooNVk3e4kA==} peerDependencies: @@ -8939,9 +8932,6 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.4.1: - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} - tslib@2.5.3: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} @@ -9181,13 +9171,11 @@ packages: vega-dataflow@5.7.5: resolution: {integrity: sha512-EdsIl6gouH67+8B0f22Owr2tKDiMPNNR8lEvJDcxmFw02nXd8juimclpLvjPQriqn6ta+3Dn5txqfD117H04YA==} - vega-embed@6.23.0: - resolution: {integrity: sha512-8Iava57LdROsatqsOhMLErHYaBpZBB7yZJlSVU3/xOK3l8Ft5WFnj5fm3OOAVML97/0yULE7LRVjXW5hV3fSpg==} + vega-embed@6.25.0: + resolution: {integrity: sha512-pK99jEhZPNYgx4daiYDyNZ7f1h2ep5PyzMYN/qKzJNxzcaNf8wgmUjHrWeJSeMh8RNyw89VRphIleeg7LNLhDA==} peerDependencies: vega: ^5.21.0 vega-lite: '*' - bundledDependencies: - - yallist vega-encode@4.9.2: resolution: {integrity: sha512-c3J0LYkgYeXQxwnYkEzL15cCFBYPRaYUon8O2SZ6O4PhH4dfFTXBzSyT8+gh8AhBd572l2yGDfxpEYA6pOqdjg==} @@ -9271,8 +9259,8 @@ packages: vega-time@2.1.1: resolution: {integrity: sha512-z1qbgyX0Af2kQSGFbApwBbX2meenGvsoX8Nga8uyWN8VIbiySo/xqizz1KrP6NbB6R+x5egKmkjdnyNThPeEWA==} - vega-tooltip@0.33.0: - resolution: {integrity: sha512-jMcvH2lP20UfyvO2KAEdloiwRyasikaiLuNFhzwrrzf2RamGTxP4G7B2OZ2QENfrGUH05Z9ei5tn/eErdzOaZQ==} + vega-tooltip@0.34.0: + resolution: {integrity: sha512-TtxwkcLZ5aWQTvKGlfWDou8tISGuxmqAW1AgGZjrDpf75qsXvgtbPdRAAls2LZMqDxpr5T1kMEZs9XbSpiI8yw==} vega-transforms@4.10.2: resolution: {integrity: sha512-sJELfEuYQ238PRG+GOqQch8D69RYnJevYSGLsRGQD2LxNz3j+GlUX6Pid+gUEH5HJy22Q5L0vsTl2ZNhIr4teQ==} @@ -15242,7 +15230,7 @@ snapshots: '@formatjs/ecma402-abstract': 1.11.4 '@formatjs/fast-memoize': 1.2.1 '@formatjs/icu-messageformat-parser': 2.1.0 - tslib: 2.4.1 + tslib: 2.6.2 invariant@2.2.4: dependencies: @@ -17459,14 +17447,6 @@ snapshots: svelte-range-slider-pips@2.0.1: {} - svelte-vega@2.0.0(svelte@4.2.15)(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0): - dependencies: - fast-deep-equal: 3.1.3 - svelte: 4.2.15 - vega: 5.23.0 - vega-embed: 6.23.0(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0) - vega-lite: 5.12.0(vega@5.23.0) - svelte2tsx@0.7.7(svelte@4.2.15)(typescript@5.4.5): dependencies: dedent-js: 1.0.1 @@ -17699,8 +17679,6 @@ snapshots: tslib@1.14.1: {} - tslib@2.4.1: {} - tslib@2.5.3: {} tslib@2.6.2: {} @@ -17937,7 +17915,7 @@ snapshots: transitivePeerDependencies: - encoding - vega-embed@6.23.0(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0): + vega-embed@6.25.0(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0): dependencies: fast-json-patch: 3.1.1 json-stringify-pretty-compact: 3.0.0 @@ -17948,7 +17926,7 @@ snapshots: vega-lite: 5.12.0(vega@5.23.0) vega-schema-url-parser: 2.2.0 vega-themes: 2.14.0(vega-lite@5.12.0(vega@5.23.0))(vega@5.23.0) - vega-tooltip: 0.33.0 + vega-tooltip: 0.34.0 vega-encode@4.9.2: dependencies: @@ -18150,7 +18128,7 @@ snapshots: d3-time: 3.1.0 vega-util: 1.17.2 - vega-tooltip@0.33.0: + vega-tooltip@0.34.0: dependencies: vega-util: 1.17.2 diff --git a/requirements.txt b/requirements.txt index c6bf0d8738b79..11fa52dfa8430 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ aiofiles>=22.0,<24.0 -altair>=4.2.0,<6.0 +altair>=5.3.0,<6.0 fastapi ffmpy gradio_client==1.0.1 From c6b43b2f68fc9de59effb7c49a0c936584f85c94 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 19 Jun 2024 20:07:08 +0000 Subject: [PATCH 02/20] add changeset --- .changeset/twenty-jokes-argue.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/twenty-jokes-argue.md diff --git a/.changeset/twenty-jokes-argue.md b/.changeset/twenty-jokes-argue.md new file mode 100644 index 0000000000000..ca5819289eb3f --- /dev/null +++ b/.changeset/twenty-jokes-argue.md @@ -0,0 +1,6 @@ +--- +"@gradio/plot": minor +"gradio": minor +--- + +feat:changes From 036eb194884626c972b5b002e1bbea7660d2b741 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 19 Jun 2024 20:08:56 +0000 Subject: [PATCH 03/20] add changeset --- .changeset/twenty-jokes-argue.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/twenty-jokes-argue.md b/.changeset/twenty-jokes-argue.md index ca5819289eb3f..37c789746838e 100644 --- a/.changeset/twenty-jokes-argue.md +++ b/.changeset/twenty-jokes-argue.md @@ -1,6 +1,6 @@ --- -"@gradio/plot": minor -"gradio": minor +"@gradio/plot": patch +"gradio": patch --- feat:changes From 71adef5f470c7794264e6a8d2628952c6e96dbd7 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 19 Jun 2024 20:10:05 +0000 Subject: [PATCH 04/20] add changeset --- .changeset/twenty-jokes-argue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twenty-jokes-argue.md b/.changeset/twenty-jokes-argue.md index 37c789746838e..4fc3e8672732f 100644 --- a/.changeset/twenty-jokes-argue.md +++ b/.changeset/twenty-jokes-argue.md @@ -3,4 +3,4 @@ "gradio": patch --- -feat:changes +feat:Improved plot rendering From 6913c1ea5435543e5421494572e37ff11472abcf Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Wed, 19 Jun 2024 17:53:25 -0700 Subject: [PATCH 05/20] changes --- demo/native_plots/bar_plot_demo.py | 2 +- demo/native_plots/scatter_plot_demo.py | 7 +++---- gradio/components/bar_plot.py | 6 +----- gradio/components/scatter_plot.py | 4 ++-- js/plot/shared/plot_types/AltairPlot.svelte | 9 +++++---- js/plot/shared/plot_types/altair_utils.ts | 9 +++++++-- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/demo/native_plots/bar_plot_demo.py b/demo/native_plots/bar_plot_demo.py index fd4e587cb2114..302765788ae6d 100644 --- a/demo/native_plots/bar_plot_demo.py +++ b/demo/native_plots/bar_plot_demo.py @@ -103,7 +103,7 @@ def bar_plot_fn(display): value="simple", label="Type of Bar Plot" ) - plot = gr.BarPlot(show_label=False, show_actions_button=True) + plot = gr.BarPlot(show_label=False) display.change(bar_plot_fn, inputs=display, outputs=plot) bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot) diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py index 6594cf1491892..8bf75908d9bd1 100644 --- a/demo/native_plots/scatter_plot_demo.py +++ b/demo/native_plots/scatter_plot_demo.py @@ -12,9 +12,9 @@ def scatter_plot_fn(dataset): value=iris, x="petalWidth", y="petalLength", - color="species", + # color="species", title="Iris Dataset", - color_legend_title="Species", + # color_legend_title="Species", x_title="Petal Width", y_title="Petal Length", tooltip=["petalWidth", "petalLength", "species"], @@ -25,11 +25,10 @@ def scatter_plot_fn(dataset): value=cars, x="Horsepower", y="Miles_per_Gallon", - color="Origin", + # color="Origin", tooltip="Name", title="Car Data", y_title="Miles per Gallon", - color_legend_title="Origin of Car", caption="MPG vs Horsepower of various cars", ) diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py index e23b6e1847fb9..f5eba6cd9d5eb 100644 --- a/gradio/components/bar_plot.py +++ b/gradio/components/bar_plot.py @@ -184,11 +184,7 @@ def create_plot( import altair as alt interactive = True if interactive is None else interactive - orientation = ( - {"field": group, "title": group_title if group_title is not None else group} - if group - else {} - ) + orientation = {"field": group, "title": group_title} if group else {} x_title = x_title or x y_title = y_title or y diff --git a/gradio/components/scatter_plot.py b/gradio/components/scatter_plot.py index a9c4cf78ab051..73a2e18f2ee68 100644 --- a/gradio/components/scatter_plot.py +++ b/gradio/components/scatter_plot.py @@ -291,7 +291,7 @@ def create_plot( "field": size, "type": "quantitative" if is_numeric_dtype(value[size]) else "nominal", "legend": AltairPlot.create_legend( - position=size_legend_position, title=size_legend_title or size + position=size_legend_position, title=size_legend_title ), } if shape: @@ -299,7 +299,7 @@ def create_plot( "field": shape, "type": "quantitative" if is_numeric_dtype(value[shape]) else "nominal", "legend": AltairPlot.create_legend( - position=shape_legend_position, title=shape_legend_title or shape + position=shape_legend_position, title=shape_legend_title ), } chart = ( diff --git a/js/plot/shared/plot_types/AltairPlot.svelte b/js/plot/shared/plot_types/AltairPlot.svelte index 7a08d1ef46744..d4293416745f9 100644 --- a/js/plot/shared/plot_types/AltairPlot.svelte +++ b/js/plot/shared/plot_types/AltairPlot.svelte @@ -31,7 +31,6 @@ $: plot = value?.plot; $: spec = JSON.parse(plot) as Spec; - $: console.log(spec); $: if (value.chart) { const config = create_config(computed_style); spec.config = config; @@ -67,13 +66,15 @@ } break; } - // Create a resize observer for element that resizes plot + $: fit_width_to_parent = + spec.encoding?.column?.field || spec.encoding?.row?.field ? false : true; // vega seems to glitch with width when orientation is set + const renderPlot = () => { - spec.width = parent_element.offsetWidth; + if (fit_width_to_parent) spec.width = parent_element.offsetWidth; vegaEmbed(element, spec, { actions: show_actions_button }); }; let resizeObserver = new ResizeObserver(() => { - if (spec.width !== parent_element.offsetWidth) { + if (fit_width_to_parent && spec.width !== parent_element.offsetWidth) { renderPlot(); } }); diff --git a/js/plot/shared/plot_types/altair_utils.ts b/js/plot/shared/plot_types/altair_utils.ts index 85ba1bc6d24bc..eda7bffeac20b 100644 --- a/js/plot/shared/plot_types/altair_utils.ts +++ b/js/plot/shared/plot_types/altair_utils.ts @@ -1,6 +1,7 @@ import type { Config as VegaConfig } from "vega"; export function create_config(computed_style: CSSStyleDeclaration): VegaConfig { + let accentColor = computed_style.getPropertyValue("--color-accent"); let bodyTextColor = computed_style.getPropertyValue("--body-text-color"); let borderColorPrimary = computed_style.getPropertyValue( "--border-color-primary" @@ -16,6 +17,11 @@ export function create_config(computed_style: CSSStyleDeclaration): VegaConfig { let textSizeSm = fontToPxVal(computed_style.getPropertyValue("--text-sm")); return { autosize: { type: "fit", contains: "padding" }, + mark: { + color: accentColor, + fillOpacity: 0.8, + + }, axis: { labelFont: fontFamily, labelColor: bodyTextColor, @@ -49,7 +55,6 @@ export function create_config(computed_style: CSSStyleDeclaration): VegaConfig { }, view: { stroke: borderColorPrimary - }, - header: { labelFont: computed_style.fontFamily, labelColor: bodyTextColor } + } }; } From 2c48b6dd9ec3ee5dee370ca073c01293e6dc3763 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Thu, 20 Jun 2024 11:18:10 -0700 Subject: [PATCH 06/20] changes --- demo/native_plots/scatter_plot_demo.py | 5 +- js/plot/shared/plot_types/AltairPlot.svelte | 50 +--------------- js/plot/shared/plot_types/altair_utils.ts | 65 ++++++++++++++++++--- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py index 8bf75908d9bd1..f2033c3a9b84f 100644 --- a/demo/native_plots/scatter_plot_demo.py +++ b/demo/native_plots/scatter_plot_demo.py @@ -12,9 +12,8 @@ def scatter_plot_fn(dataset): value=iris, x="petalWidth", y="petalLength", - # color="species", + color=None, title="Iris Dataset", - # color_legend_title="Species", x_title="Petal Width", y_title="Petal Length", tooltip=["petalWidth", "petalLength", "species"], @@ -25,7 +24,7 @@ def scatter_plot_fn(dataset): value=cars, x="Horsepower", y="Miles_per_Gallon", - # color="Origin", + color="Origin", tooltip="Name", title="Car Data", y_title="Miles per Gallon", diff --git a/js/plot/shared/plot_types/AltairPlot.svelte b/js/plot/shared/plot_types/AltairPlot.svelte index d4293416745f9..7e68cbd1f2d42 100644 --- a/js/plot/shared/plot_types/AltairPlot.svelte +++ b/js/plot/shared/plot_types/AltairPlot.svelte @@ -1,8 +1,6 @@ -{#if value && type == "plotly"} - -{:else if type == "bokeh"} - -{:else if type == "altair"} - -{:else if type == "matplotlib"} - {:else} {/if} From 605b322beef5eb12f98372dad567245c090b5a88 Mon Sep 17 00:00:00 2001 From: aliabid94 Date: Thu, 20 Jun 2024 14:21:36 -0700 Subject: [PATCH 14/20] Update twenty-jokes-argue.md --- .changeset/twenty-jokes-argue.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/twenty-jokes-argue.md b/.changeset/twenty-jokes-argue.md index 4fc3e8672732f..2e8f9e6c07a4f 100644 --- a/.changeset/twenty-jokes-argue.md +++ b/.changeset/twenty-jokes-argue.md @@ -3,4 +3,5 @@ "gradio": patch --- -feat:Improved plot rendering +feat:Improved plot rendering to thematically match +highlight:Expect visual changes in gr.Plot, gr.BarPlot, gr.LinePlot, gr.ScatterPlot, including changes to color and width sizing. From 85f0ed105fe87025463f63b84a413566177c3241 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Thu, 20 Jun 2024 14:22:01 -0700 Subject: [PATCH 15/20] changes --- demo/native_plots/line_plot_demo.py | 8 ------- demo/native_plots/scatter_plot_demo.py | 4 ++++ gradio/components/bar_plot.py | 23 +++++++++++++++------ gradio/components/line_plot.py | 19 +++++++++++++---- gradio/components/scatter_plot.py | 19 +++++++++++++---- js/plot/shared/plot_types/AltairPlot.svelte | 16 +++++++++++++- 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/demo/native_plots/line_plot_demo.py b/demo/native_plots/line_plot_demo.py index 1c88b1fe5bab6..a87e9d72ce74a 100644 --- a/demo/native_plots/line_plot_demo.py +++ b/demo/native_plots/line_plot_demo.py @@ -24,8 +24,6 @@ def line_plot_fn(dataset): overlay_point=False, title="Stock Prices", stroke_dash_legend_title=None, - height=300, - width=500 ) elif dataset == "climate": return gr.LinePlot( @@ -40,8 +38,6 @@ def line_plot_fn(dataset): overlay_point=False, title="Climate", stroke_dash_legend_title=None, - height=300, - width=500 ) elif dataset == "seattle_weather": return gr.LinePlot( @@ -56,8 +52,6 @@ def line_plot_fn(dataset): overlay_point=True, title="Seattle Weather", stroke_dash_legend_title=None, - height=300, - width=500 ) elif dataset == "gapminder": return gr.LinePlot( @@ -72,8 +66,6 @@ def line_plot_fn(dataset): overlay_point=False, title="Life expectancy for countries", stroke_dash_legend_title="Country Cluster", - height=300, - width=500 ) diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py index f2033c3a9b84f..54d9210552030 100644 --- a/demo/native_plots/scatter_plot_demo.py +++ b/demo/native_plots/scatter_plot_demo.py @@ -18,6 +18,8 @@ def scatter_plot_fn(dataset): y_title="Petal Length", tooltip=["petalWidth", "petalLength", "species"], caption="", + height=600, + width=600, ) else: return gr.ScatterPlot( @@ -29,6 +31,8 @@ def scatter_plot_fn(dataset): title="Car Data", y_title="Miles per Gallon", caption="MPG vs Horsepower of various cars", + height=None, + width=None, ) diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py index f5eba6cd9d5eb..de0d7f1200bc7 100644 --- a/gradio/components/bar_plot.py +++ b/gradio/components/bar_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import TYPE_CHECKING, Any, Callable, Literal from gradio_client.documentation import document @@ -52,8 +53,8 @@ def __init__( "none", ] | None = None, - height: int | str | None = None, - width: int | str | None = None, + height: int | None = None, + width: int | None = None, y_lim: list[int] | None = None, caption: str | None = None, interactive: bool | None = True, @@ -88,8 +89,8 @@ def __init__( color_legend_title: The title given to the color legend. By default, uses the value of color parameter. group_title: The label displayed on top of the subplot columns (or rows if vertical=True). Use an empty string to omit. color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. - height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. - width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. + height: The height of the plot in pixels. + width: The width of the plot in pixels. If None, expands to fit. y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max]. caption: The (optional) caption to display below the plot. interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad. @@ -122,6 +123,16 @@ def __init__( self.y_lim = y_lim self.caption = caption self.interactive_chart = interactive + if isinstance(width, str): + width = None + warnings.warn( + "Width should be an integer, not a string. Setting width to None." + ) + if isinstance(height, str): + warnings.warn( + "Height should be an integer, not a string. Setting height to None." + ) + height = None self.width = width self.height = height self.sort = sort @@ -174,8 +185,8 @@ def create_plot( "none", ] | None = None, - height: int | str | None = None, - width: int | str | None = None, + height: int | None = None, + width: int | None = None, y_lim: list[int] | None = None, interactive: bool | None = True, sort: Literal["x", "y", "-x", "-y"] | None = None, diff --git a/gradio/components/line_plot.py b/gradio/components/line_plot.py index 138b87849b212..7a19fe06436ec 100644 --- a/gradio/components/line_plot.py +++ b/gradio/components/line_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import TYPE_CHECKING, Any, Callable, Literal from gradio_client.documentation import document @@ -64,8 +65,8 @@ def __init__( "none", ] | None = None, - height: int | str | None = None, - width: int | str | None = None, + height: int | None = None, + width: int | None = None, x_lim: list[int] | None = None, y_lim: list[int] | None = None, caption: str | None = None, @@ -101,8 +102,8 @@ def __init__( stroke_dash_legend_title: The title given to the stroke_dash legend. By default, uses the value of the stroke_dash parameter. color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. stroke_dash_legend_position: The position of the stoke_dash legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. - height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. - width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. + height: The height of the plot in pixels. + width: The width of the plot in pixels. If None, expands to fit. x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max]. y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max]. caption: The (optional) caption to display below the plot. @@ -136,6 +137,16 @@ def __init__( self.y_lim = y_lim self.caption = caption self.interactive_chart = interactive + if isinstance(width, str): + width = None + warnings.warn( + "Width should be an integer, not a string. Setting width to None." + ) + if isinstance(height, str): + warnings.warn( + "Height should be an integer, not a string. Setting height to None." + ) + height = None self.width = width self.height = height self.show_actions_button = show_actions_button diff --git a/gradio/components/scatter_plot.py b/gradio/components/scatter_plot.py index 73a2e18f2ee68..602287eaad391 100644 --- a/gradio/components/scatter_plot.py +++ b/gradio/components/scatter_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import TYPE_CHECKING, Any, Callable, Literal from gradio_client.documentation import document @@ -77,8 +78,8 @@ def __init__( "none", ] | None = None, - height: int | str | None = None, - width: int | str | None = None, + height: int | None = None, + width: int | None = None, x_lim: list[int | float] | None = None, y_lim: list[int | float] | None = None, caption: str | None = None, @@ -116,8 +117,8 @@ def __init__( color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. size_legend_position: The position of the size legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. shape_legend_position: The position of the shape legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. - height: The height of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. - width: The width of the plot, specified in pixels if a number is passed, or in CSS units if a string is passed. + height: The height of the plot in pixels. + width: The width of the plot in pixels. If None, expands to fit. x_lim: A tuple or list containing the limits for the x-axis, specified as [x_min, x_max]. y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max]. caption: The (optional) caption to display below the plot. @@ -151,6 +152,16 @@ def __init__( self.shape_legend_position = shape_legend_position self.caption = caption self.interactive_chart = interactive + if isinstance(width, str): + width = None + warnings.warn( + "Width should be an integer, not a string. Setting width to None." + ) + if isinstance(height, str): + warnings.warn( + "Height should be an integer, not a string. Setting height to None." + ) + height = None self.width = width self.height = height self.x_lim = x_lim diff --git a/js/plot/shared/plot_types/AltairPlot.svelte b/js/plot/shared/plot_types/AltairPlot.svelte index 5ab360fb42f15..6062c334c0c81 100644 --- a/js/plot/shared/plot_types/AltairPlot.svelte +++ b/js/plot/shared/plot_types/AltairPlot.svelte @@ -15,8 +15,17 @@ let computed_style = window.getComputedStyle(target); + let old_spec: Spec; + let spec_width: number; $: plot = value?.plot; $: spec = JSON.parse(plot) as Spec; + $: if (old_spec !== spec) { + console.log("spec changed"); + old_spec = spec; + spec_width = spec.width; + console.log(spec_width); + } + $: if (value.chart) { spec = set_config(spec, computed_style, value.chart as string, colors); } @@ -24,7 +33,12 @@ spec.encoding?.column?.field || spec.encoding?.row?.field ? false : true; // vega seems to glitch with width when orientation is set const renderPlot = (): void => { - if (fit_width_to_parent) spec.width = parent_element.offsetWidth; + if (fit_width_to_parent) { + spec.width = Math.min( + parent_element.offsetWidth, + spec_width || parent_element.offsetWidth + ); + } vegaEmbed(element, spec, { actions: show_actions_button }); }; let resizeObserver = new ResizeObserver(() => { From ff2fb5e557c0a371d6de46ff61da3f73cc60d495 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Thu, 20 Jun 2024 14:37:49 -0700 Subject: [PATCH 16/20] chanegs --- js/plot/Plot.stories.svelte | 33 +++++++++++++++++++-- js/plot/shared/plot_types/AltairPlot.svelte | 2 -- js/plot/testplot.js | 26 +++++++++++++++- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/js/plot/Plot.stories.svelte b/js/plot/Plot.stories.svelte index a65e7c2400d2d..6ef3e1f380273 100644 --- a/js/plot/Plot.stories.svelte +++ b/js/plot/Plot.stories.svelte @@ -2,7 +2,13 @@ import { Template, Story } from "@storybook/addon-svelte-csf"; import PlotComponent from "./Index.svelte"; import { allModes } from "../storybook/modes"; - import { test_plot } from "./testplot"; + import { + matplotlib_plot, + line_plot, + multi_line_plot, + bar_plot, + scatter_plot + } from "./testplot"; export const meta = { title: "Components/Plot", @@ -23,13 +29,34 @@ + + + + + + Date: Thu, 20 Jun 2024 15:06:32 -0700 Subject: [PATCH 17/20] changes --- js/plot/Plot.stories.svelte | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/js/plot/Plot.stories.svelte b/js/plot/Plot.stories.svelte index 6ef3e1f380273..8c65a298a6e73 100644 --- a/js/plot/Plot.stories.svelte +++ b/js/plot/Plot.stories.svelte @@ -41,6 +41,9 @@ args={{ value: line_plot }} + parameters={{ + chromatic: { delay: 1000 } + }} /> + + Date: Thu, 20 Jun 2024 15:18:36 -0700 Subject: [PATCH 18/20] changes --- js/plot/Plot.stories.svelte | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/js/plot/Plot.stories.svelte b/js/plot/Plot.stories.svelte index 8c65a298a6e73..8e3c2356cc837 100644 --- a/js/plot/Plot.stories.svelte +++ b/js/plot/Plot.stories.svelte @@ -2,13 +2,7 @@ import { Template, Story } from "@storybook/addon-svelte-csf"; import PlotComponent from "./Index.svelte"; import { allModes } from "../storybook/modes"; - import { - matplotlib_plot, - line_plot, - multi_line_plot, - bar_plot, - scatter_plot - } from "./testplot"; + import { matplotlib_plot } from "./testplot"; export const meta = { title: "Components/Plot", @@ -17,10 +11,10 @@ chromatic: { modes: { desktop: allModes["desktop"], - mobile: allModes["mobile"] - } - } - } + mobile: allModes["mobile"], + }, + }, + }, }; @@ -32,10 +26,11 @@ name="with matplotlib value" args={{ value: matplotlib_plot, - label: "Plot" + label: "Plot", }} /> + From ab3de66b80d4393f21e378feaf918cdad23ffa78 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Thu, 20 Jun 2024 15:22:12 -0700 Subject: [PATCH 19/20] changes --- js/plot/Plot.stories.svelte | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/plot/Plot.stories.svelte b/js/plot/Plot.stories.svelte index 8e3c2356cc837..e4d4eb5ee8cc4 100644 --- a/js/plot/Plot.stories.svelte +++ b/js/plot/Plot.stories.svelte @@ -11,10 +11,10 @@ chromatic: { modes: { desktop: allModes["desktop"], - mobile: allModes["mobile"], - }, - }, - }, + mobile: allModes["mobile"] + } + } + } }; @@ -26,7 +26,7 @@ name="with matplotlib value" args={{ value: matplotlib_plot, - label: "Plot", + label: "Plot" }} /> @@ -74,6 +74,6 @@ From 271c4e87938f35a1ec686bb51dde812e5106cd57 Mon Sep 17 00:00:00 2001 From: Ali Abid Date: Thu, 20 Jun 2024 15:57:09 -0700 Subject: [PATCH 20/20] changes --- js/plot/shared/Plot.svelte | 14 +++++++++----- js/plot/shared/plot_types/AltairPlot.svelte | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/js/plot/shared/Plot.svelte b/js/plot/shared/Plot.svelte index 9e3b692df9be5..ca5e1c41f3782 100644 --- a/js/plot/shared/Plot.svelte +++ b/js/plot/shared/Plot.svelte @@ -3,7 +3,6 @@ import { Plot as PlotIcon } from "@gradio/icons"; import { Empty } from "@gradio/atoms"; import type { ThemeMode } from "js/app/src/components/types"; - import { beforeUpdate } from "svelte"; export let value; export let target: HTMLElement; @@ -14,6 +13,7 @@ export let show_actions_button: bool; let PlotComponent: any = null; + let _type = value?.type; const plotTypeMapping = { plotly: () => import("./plot_types/PlotlyPlot.svelte"), @@ -22,13 +22,17 @@ matplotlib: () => import("./plot_types/MatplotlibPlot.svelte") }; - beforeUpdate(async () => { + $: { let type = value?.type; + if (type !== _type) { + PlotComponent = null; + } if (type && type in plotTypeMapping) { - const module = await plotTypeMapping[type](); - PlotComponent = module.default; + plotTypeMapping[type]().then((module) => { + PlotComponent = module.default; + }); } - }); + } {#if value && PlotComponent} diff --git a/js/plot/shared/plot_types/AltairPlot.svelte b/js/plot/shared/plot_types/AltairPlot.svelte index 52bc9ffe459ae..e30cb0b20f9d2 100644 --- a/js/plot/shared/plot_types/AltairPlot.svelte +++ b/js/plot/shared/plot_types/AltairPlot.svelte @@ -1,7 +1,7 @@