Skip to content

Commit

Permalink
Result Panel Improvements (#2665)
Browse files Browse the repository at this point in the history
This PR resets the margins of each visualization plot in the result
panel. The title of each plot is removed, and the name of each operator
will be displayed in the result panel title (once the operator is
highlighted).

This PR also modifies the python console display, making it consistent
with the result panel.


https://github.com/Texera/texera/assets/86388854/f5e8f69e-f00a-40a0-8e09-4c052045be48

---------

Co-authored-by: mengw15 <[email protected]>
Co-authored-by: Xinyuan Lin <[email protected]>
  • Loading branch information
3 people authored May 23, 2024
1 parent 8bedb44 commit 5d03929
Show file tree
Hide file tree
Showing 27 changed files with 177 additions and 266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ class DotPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor
@AutofillAttributeName
var countAttribute: String = ""

@JsonProperty(value = "Title", required = true)
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Title for the Dot Plot Visualization")
var title: String = ""

override def getOutputSchema(schemas: Array[Schema]): Schema = {
Schema.builder().add(new Attribute("html-content", AttributeType.STRING)).build()
}
Expand All @@ -46,43 +41,38 @@ class DotPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor
|
| fig.update_traces(marker=dict(size=12, line=dict(width=2, color='DarkSlateGrey')))
|
| fig.update_layout(title='$title',
| xaxis_title='Counts',
| yaxis_title='$countAttribute',
| yaxis=dict(showline=True, showgrid=False, showticklabels=True),
| xaxis=dict(showline=True, showgrid=True, showticklabels=True),
| height=800)
| fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
|""".stripMargin
}

override def generatePythonCode(): String = {
val finalCode = s"""
|from pytexera import *
|
|import plotly.express as px
|import plotly.graph_objects as go
|import plotly.io
|
|class ProcessTableOperator(UDFTableOperator):
|
| def render_error(self, error_msg):
| return '''<h1>DotPlot is not available.</h1>
| <p>Reasons are: {} </p>
| '''.format(error_msg)
|
| @overrides
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
| if table.empty:
| yield {'html-content': self.render_error("Input table is empty.")}
| return
| ${createPlotlyFigure()}
| if table.empty:
| yield {'html-content': self.render_error("No valid rows left (every row has at least 1 missing value).")}
| return
| # convert fig to html content
| html = plotly.io.to_html(fig, include_plotlyjs='cdn', auto_play=False)
| yield {'html-content': html}
|""".stripMargin
|from pytexera import *
|
|import plotly.express as px
|import plotly.graph_objects as go
|import plotly.io
|
|class ProcessTableOperator(UDFTableOperator):
|
| def render_error(self, error_msg):
| return '''<h1>DotPlot is not available.</h1>
| <p>Reasons are: {} </p>
| '''.format(error_msg)
|
| @overrides
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
| if table.empty:
| yield {'html-content': self.render_error("Input table is empty.")}
| return
| ${createPlotlyFigure()}
| if table.empty:
| yield {'html-content': self.render_error("No valid rows left (every row has at least 1 missing value).")}
| return
| # convert fig to html content
| html = plotly.io.to_html(fig, include_plotlyjs='cdn', auto_play=False)
| yield {'html-content': html}
|""".stripMargin
finalCode
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ class ScatterMatrixChartOpDesc extends VisualizationOperator with PythonOperator
@AutofillAttributeName
var color: String = ""

@JsonProperty(value = "title", required = true, defaultValue = "Scatter Matrix Chart")
@JsonSchemaTitle("Title")
@JsonPropertyDescription("the title of the matrix chart")
var title: String = "Scatter Matrix Chart"

override def getOutputSchema(schemas: Array[Schema]): Schema = {
Schema.builder().add(new Attribute("html-content", AttributeType.STRING)).build()
}
Expand All @@ -62,11 +57,7 @@ class ScatterMatrixChartOpDesc extends VisualizationOperator with PythonOperator
val list_Attributes = selectedAttributes.map(attribute => s""""$attribute"""").mkString(",")
s"""
| fig = px.scatter_matrix(table, dimensions=[$list_Attributes], color='$color')
| fig.update_layout(
| title='$title',
| width=800,
| height=800
| )
| fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
|""".stripMargin
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ import edu.uci.ics.texera.workflow.operators.visualization.{
""")
class BarChartOpDesc extends VisualizationOperator with PythonOperatorDescriptor {

@JsonProperty(defaultValue = "Bar Graph Visual")
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Add a title to your visualization")
var title: String = ""

@JsonProperty(value = "value", required = true)
@JsonSchemaTitle("Value Column")
@JsonPropertyDescription("the value associated with each category")
Expand Down Expand Up @@ -84,41 +79,42 @@ class BarChartOpDesc extends VisualizationOperator with PythonOperatorDescriptor
isCategoryColumn = "True"

val finalCode = s"""
|from pytexera import *
|
|import plotly.express as px
|import pandas as pd
|import plotly.graph_objects as go
|import plotly.io
|import json
|import pickle
|import plotly
|
|class ProcessTableOperator(UDFTableOperator):
|
| # Generate custom error message as html string
| def render_error(self, error_msg) -> str:
| return '''<h1>Bar chart is not available.</h1>
| <p>Reason is: {} </p>
| '''.format(error_msg)
|
| @overrides
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
| ${manipulateTable()}
| if not table.empty and '$fields' != '$value':
| if $isHorizontalOrientation:
| fig = go.Figure(px.bar(table, y='$fields', x='$value', color="$categoryColumn" if $isCategoryColumn else None, orientation = 'h', title='$title'))
| else:
| fig = go.Figure(px.bar(table, y='$value', x='$fields', color="$categoryColumn" if $isCategoryColumn else None, title='$title'))
| html = plotly.io.to_html(fig, include_plotlyjs = 'cdn', auto_play = False)
| # use latest plotly lib in html
| #html = html.replace('https://cdn.plot.ly/plotly-2.3.1.min.js', 'https://cdn.plot.ly/plotly-2.18.2.min.js')
| elif '$fields' == '$value':
| html = self.render_error('Fields should not have the same value.')
| elif table.empty:
| html = self.render_error('Table should not have any empty/null values or fields.')
| yield {'html-content':html}
| """.stripMargin
|from pytexera import *
|
|import plotly.express as px
|import pandas as pd
|import plotly.graph_objects as go
|import plotly.io
|import json
|import pickle
|import plotly
|
|class ProcessTableOperator(UDFTableOperator):
|
| # Generate custom error message as html string
| def render_error(self, error_msg) -> str:
| return '''<h1>Bar chart is not available.</h1>
| <p>Reason is: {} </p>
| '''.format(error_msg)
|
| @overrides
| def process_table(self, table: Table, port: int) -> Iterator[Optional[TableLike]]:
| ${manipulateTable()}
| if not table.empty and '$fields' != '$value':
| if $isHorizontalOrientation:
| fig = go.Figure(px.bar(table, y='$fields', x='$value', color="$categoryColumn" if $isCategoryColumn else None, orientation = 'h'))
| else:
| fig = go.Figure(px.bar(table, y='$value', x='$fields', color="$categoryColumn" if $isCategoryColumn else None))
| fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
| html = plotly.io.to_html(fig, include_plotlyjs = 'cdn', auto_play = False)
| # use latest plotly lib in html
| #html = html.replace('https://cdn.plot.ly/plotly-2.3.1.min.js', 'https://cdn.plot.ly/plotly-2.18.2.min.js')
| elif '$fields' == '$value':
| html = self.render_error('Fields should not have the same value.')
| elif table.empty:
| html = self.render_error('Table should not have any empty/null values or fields.')
| yield {'html-content':html}
| """.stripMargin
finalCode
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ import edu.uci.ics.texera.workflow.operators.visualization.{
""")
class BoxPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor {

@JsonProperty(defaultValue = "Box Plot Visual")
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Add a title to your visualization")
var title: String = ""

@JsonProperty(value = "value", required = true)
@JsonSchemaTitle("Value Column")
@JsonPropertyDescription("Data Column for Boxplot")
Expand Down Expand Up @@ -77,9 +72,7 @@ class BoxPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor
| else:
| fig = px.box(table, y='$value',boxmode="overlay", points='all')
| fig.update_traces(quartilemethod="${quertiletype.getQuartiletype}", jitter=0, col=1)
|
|
|
| fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
|""".stripMargin
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@ class BubbleChartOpDesc extends VisualizationOperator with PythonOperatorDescrip
@JsonPropertyDescription("Data column to determine bubble size")
@AutofillAttributeName var zValue: String = ""

@JsonProperty(value = "title", required = true)
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Title of Chart")
var title: String = "My Bubble Chart"

@JsonProperty(value = "enableColor", defaultValue = "false")
@JsonSchemaTitle("Enable Color")
@JsonPropertyDescription("Colors bubbles using a data column")
Expand Down Expand Up @@ -80,9 +75,9 @@ class BubbleChartOpDesc extends VisualizationOperator with PythonOperatorDescrip
assert(xValue.nonEmpty && yValue.nonEmpty && zValue.nonEmpty)
s"""
| if '$enableColor' == 'true':
| fig = go.Figure(px.scatter(table, x='$xValue', y='$yValue', size='$zValue', size_max=100, title='$title', color='$colorCategory'))
| fig = go.Figure(px.scatter(table, x='$xValue', y='$yValue', size='$zValue', size_max=100, color='$colorCategory'))
| else:
| fig = go.Figure(px.scatter(table, x='$xValue', y='$yValue', size='$zValue', size_max=100, title='$title'))
| fig = go.Figure(px.scatter(table, x='$xValue', y='$yValue', size='$zValue', size_max=100))
|""".stripMargin
}

Expand Down Expand Up @@ -113,6 +108,7 @@ class BubbleChartOpDesc extends VisualizationOperator with PythonOperatorDescrip
| if table.empty:
| yield {'html-content': self.render_error("No valid rows left (every row has at least 1 missing value).")}
| return
| fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
| html = plotly.io.to_html(fig, include_plotlyjs = 'cdn', auto_play = False)
| yield {'html-content':html}
|""".stripMargin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ import scala.jdk.CollectionConverters.CollectionHasAsScala
""")
class DumbbellPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor {

@JsonProperty(value = "title", required = false, defaultValue = "DumbbellPlot Visualization")
@JsonSchemaTitle("Title")
@JsonPropertyDescription("the title of this dumbbell plots")
var title: String = "DumbbellPlot Visualization"

@JsonProperty(value = "categoryColumnName", required = true)
@JsonSchemaTitle("Category Column Name")
@JsonPropertyDescription("the name of the category column")
Expand Down Expand Up @@ -106,12 +101,10 @@ class DumbbellPlotOpDesc extends VisualizationOperator with PythonOperatorDescri
| name=entity,
| line=dict(color=color)))
|
| fig.update_layout(title="${title}",
| xaxis_title="${measurementColumnName}",
| fig.update_layout(xaxis_title="${measurementColumnName}",
| yaxis_title="${comparedColumnName}",
| yaxis=dict(categoryorder='array', categoryarray=entityNames),
| ${showLegendsOption},
| height=20 * len(entityNames)
| ${showLegendsOption}
| )
|""".stripMargin
}
Expand Down Expand Up @@ -168,6 +161,7 @@ class DumbbellPlotOpDesc extends VisualizationOperator with PythonOperatorDescri
| ${createPlotlyDumbbellLineFigure()}
| ${addPlotlyDots()}
| # convert fig to html content
| fig.update_layout(margin=dict(l=0, r=0, b=60, t=0))
| html = plotly.io.to_html(fig, include_plotlyjs='cdn', auto_play=False)
| yield {'html-content': html}
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ import edu.uci.ics.texera.workflow.operators.visualization.{

class FilledAreaPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor {

@JsonProperty(required = true)
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Title of our plot")
var title: String = ""

@JsonProperty(required = true)
@JsonSchemaTitle("X-axis Attribute")
@JsonPropertyDescription("The attribute for your x-axis")
Expand Down Expand Up @@ -74,7 +69,7 @@ class FilledAreaPlotOpDesc extends VisualizationOperator with PythonOperatorDesc
val lineGroupArg = if (lineGroup.nonEmpty) s""", line_group="$lineGroup"""" else ""

s"""
| fig = px.area(table, x="$x", y="$y", title="$title"$colorArg$facetColumnArg$lineGroupArg)
| fig = px.area(table, x="$x", y="$y"$colorArg$facetColumnArg$lineGroupArg)
|""".stripMargin
}

Expand Down Expand Up @@ -121,6 +116,7 @@ class FilledAreaPlotOpDesc extends VisualizationOperator with PythonOperatorDesc
|
| if error == "":
| ${createPlotlyFigure()}
| fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
|
| html = plotly.io.to_html(fig, include_plotlyjs='cdn', auto_play=False)
| yield {'html-content': html}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ import edu.uci.ics.texera.workflow.operators.visualization.{
}
""")
class FunnelPlotOpDesc extends VisualizationOperator with PythonOperatorDescriptor {
@JsonProperty(value = "title", required = true, defaultValue = "Funnel Plot")
@JsonSchemaTitle("Plot Title")
@JsonPropertyDescription("The value for the plot title")
var title: String = "Funnel Plot"

@JsonProperty(required = true)
@JsonSchemaTitle("X Column")
Expand Down Expand Up @@ -63,12 +59,11 @@ class FunnelPlotOpDesc extends VisualizationOperator with PythonOperatorDescript
s"""
| fig = go.Figure(px.funnel(table, x ="$x", y = "$y"$colorArg))
| fig.update_layout(
| title='$title',
| scene=dict(
| xaxis_title='X: $x',
| yaxis_title='Y: $y',
| ),
| margin=dict(t=40, b=30, l=10, r=10)
| margin=dict(t=0, b=0, l=0, r=0)
| )
|""".stripMargin
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class GanttChartOpDesc extends VisualizationOperator with PythonOperatorDescript
s"""
| fig = px.timeline(table, x_start='$start', x_end='$finish', y='$task' $colorSetting)
| fig.update_yaxes(autorange='reversed')
| fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
|""".stripMargin

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import edu.uci.ics.texera.workflow.operators.visualization.{
}

class HeatMapOpDesc extends VisualizationOperator with PythonOperatorDescriptor {
@JsonProperty(defaultValue = "HeatMap", required = true)
@JsonSchemaTitle("Title")
@JsonPropertyDescription("Add a title to your visualization")
var title: String = ""

@JsonProperty(value = "x", required = true)
@JsonSchemaTitle("Value X Column")
Expand Down Expand Up @@ -55,7 +51,7 @@ class HeatMapOpDesc extends VisualizationOperator with PythonOperatorDescriptor
assert(value.nonEmpty)
s"""
| heatmap = go.Heatmap(z=table["$value"],x=table["$x"],y=table["$y"])
| layout = go.Layout(title='$title')
| layout = go.Layout(margin=dict(l=0, r=0, b=0, t=0))
| fig = go.Figure(data=[heatmap], layout=layout)
|""".stripMargin
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class HierarchyChartOpDesc extends VisualizationOperator with PythonOperatorDesc
| return
| ${createPlotlyFigure()}
| # convert fig to html content
| fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
| html = plotly.io.to_html(fig, include_plotlyjs='cdn', auto_play=False)
| yield {'html-content': html}
|""".stripMargin
Expand Down
Loading

0 comments on commit 5d03929

Please sign in to comment.