A modern, enterprise-ready business intelligence web application for data exploration and visualization.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Extensible visualization system supporting 40+ chart types with custom plugin architecture and data processing pipeline.
Core visualization framework for creating chart types.
class BaseViz:
"""Base class for all visualizations."""
viz_type: str # Unique chart type identifier
verbose_name: str # Display name for chart type
is_timeseries: bool = False # Whether chart supports time series
default_are_zeros: bool = True # How to handle missing data
credits: str = "" # Attribution for chart type
def __init__(self, datasource: BaseDatasource, form_data: Dict[str, Any],
force: bool = False):
"""
Initialize visualization.
Args:
datasource: Data source for chart
form_data: Chart configuration from UI
force: Force refresh of cached data
"""
def get_query_object(self) -> QueryObject:
"""
Build query object from form data.
Returns:
Query object for data retrieval
"""
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process DataFrame into visualization-ready format.
Args:
df: Raw query results
Returns:
Processed data for frontend rendering
"""
def get_csv(self) -> str:
"""
Export chart data as CSV.
Returns:
CSV-formatted chart data
"""
def get_json_data(self, force: bool = False) -> Dict[str, Any]:
"""
Get chart data as JSON.
Args:
force: Force refresh of cached data
Returns:
Chart data and metadata
"""
class TimeSeriesViz(BaseViz):
"""Base class for time series visualizations."""
is_timeseries: bool = True
def process_data(self, df: pd.DataFrame,
aggregate: bool = False) -> Dict[str, Any]:
"""
Process time series data.
Args:
df: Time series DataFrame
aggregate: Whether to aggregate data
Returns:
Processed time series data
"""
def to_series(self, df: pd.DataFrame, classed: str = "",
title_suffix: str = "") -> List[Dict[str, Any]]:
"""
Convert DataFrame to time series format.
Args:
df: Source DataFrame
classed: CSS class for series
title_suffix: Suffix for series titles
Returns:
List of time series objects
"""Registry system for available chart types and their implementations.
# Chart Type Registry
viz_types: Dict[str, Type[BaseViz]] = {
'table': TableViz,
'bar': DistributionBarViz,
'line': LineViz,
'area': AreaViz,
'pie': PieViz,
'scatter': ScatterViz,
'bubble': BubbleViz,
'histogram': HistogramViz,
'box_plot': BoxPlotViz,
'sunburst': SunburstViz,
'treemap': TreemapViz,
'heatmap': HeatmapViz,
'deck_scatter': DeckScatterViz,
'deck_arc': DeckArcViz,
'deck_hex': DeckHexViz,
'deck_grid': DeckGridViz,
'deck_polygon': DeckPolygonViz,
'deck_geojson': DeckGeoJsonViz,
'pivot_table': PivotTableViz,
'paired_ttest': PairedTTestViz,
'rose': RoseViz,
'partition': PartitionViz,
'event_flow': EventFlowViz,
'parallel_coordinates': ParallelCoordinatesViz,
'sankey': SankeyViz,
'chord': ChordViz,
'country_map': CountryMapViz,
'world_map': WorldMapViz,
'filter_box': FilterBoxViz,
'iframe': IFrameViz,
'para': ParaViz,
'markup': MarkupViz,
'separator': SeparatorViz,
'word_cloud': WordCloudViz,
'mapbox': MapboxViz,
}
def get_viz(viz_type: str, datasource: BaseDatasource,
form_data: Dict[str, Any] = None, **kwargs) -> BaseViz:
"""
Get visualization instance by type.
Args:
viz_type: Chart type identifier
datasource: Data source
form_data: Chart configuration
Returns:
Visualization instance
Raises:
Exception: If viz_type not found
"""
def get_all_viz_types() -> List[Dict[str, Any]]:
"""
Get metadata for all available chart types.
Returns:
List of chart type metadata
"""Implementation of popular chart types.
class TableViz(BaseViz):
"""Tabular data visualization."""
viz_type = "table"
verbose_name = "Table View"
is_timeseries = False
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process data for table display.
Args:
df: Query results DataFrame
Returns:
Table data with formatting and pagination
"""
class LineViz(TimeSeriesViz):
"""Line chart visualization."""
viz_type = "line"
verbose_name = "Time Series - Line Chart"
default_are_zeros = False
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process data for line chart.
Args:
df: Time series DataFrame
Returns:
Line chart data with series and formatting
"""
class BarViz(BaseViz):
"""Bar chart visualization."""
viz_type = "bar"
verbose_name = "Bar Chart"
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process data for bar chart.
Args:
df: Grouped DataFrame
Returns:
Bar chart data with categories and values
"""
class PieViz(BaseViz):
"""Pie chart visualization."""
viz_type = "pie"
verbose_name = "Pie Chart"
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process data for pie chart.
Args:
df: Aggregated DataFrame
Returns:
Pie chart data with segments and percentages
"""
class ScatterViz(BaseViz):
"""Scatter plot visualization."""
viz_type = "scatter"
verbose_name = "Scatter Plot"
def get_data(self, df: pd.DataFrame) -> VizData:
"""
Process data for scatter plot.
Args:
df: Point data DataFrame
Returns:
Scatter plot data with coordinates and metadata
"""System for translating UI form data into database queries.
class QueryObject:
"""Query specification for data retrieval."""
def __init__(self,
datasource: BaseDatasource,
metrics: List[str] = None,
groupby: List[str] = None,
columns: List[str] = None,
granularity: str = None,
since: str = None,
until: str = None,
filters: List[Dict[str, Any]] = None,
row_limit: int = None,
row_offset: int = None,
order_desc: bool = True,
extras: Dict[str, Any] = None):
"""
Initialize query object.
Args:
datasource: Target datasource
metrics: List of metrics to calculate
groupby: Columns to group by
columns: Specific columns to include
granularity: Time granularity for time series
since: Start time for time range
until: End time for time range
filters: List of filter conditions
row_limit: Maximum rows to return
row_offset: Number of rows to skip
order_desc: Sort order (descending if True)
extras: Additional query parameters
"""
self.datasource = datasource
self.metrics = metrics or []
self.groupby = groupby or []
self.columns = columns or []
self.granularity = granularity
self.since = since
self.until = until
self.filters = filters or []
self.row_limit = row_limit
self.row_offset = row_offset
self.order_desc = order_desc
self.extras = extras or {}
def to_dict(self) -> Dict[str, Any]:
"""Convert query object to dictionary."""
@classmethod
def from_dict(cls, obj_dict: Dict[str, Any]) -> 'QueryObject':
"""Create query object from dictionary."""
def get_query_results(query_obj: QueryObject,
force_cached: bool = False) -> Dict[str, Any]:
"""
Execute query and return results.
Args:
query_obj: Query specification
force_cached: Use cached results if available
Returns:
Query results with data and metadata
"""System for processing raw query results into visualization formats.
class DataProcessor:
"""Data processing utilities for visualizations."""
@staticmethod
def pivot_df(df: pd.DataFrame, rows: List[str], cols: List[str],
metric: str, aggfunc: str = 'sum',
fill_value: Any = 0) -> pd.DataFrame:
"""
Pivot DataFrame for cross-tabulation.
Args:
df: Source DataFrame
rows: Row dimension columns
cols: Column dimension columns
metric: Value column to aggregate
aggfunc: Aggregation function
fill_value: Value for missing cells
Returns:
Pivoted DataFrame
"""
@staticmethod
def flatten_df(df: pd.DataFrame) -> pd.DataFrame:
"""
Flatten DataFrame with MultiIndex columns.
Args:
df: DataFrame to flatten
Returns:
DataFrame with single-level column index
"""
@staticmethod
def apply_time_grain(df: pd.DataFrame, time_grain: str,
time_col: str) -> pd.DataFrame:
"""
Apply time granularity to DataFrame.
Args:
df: Time series DataFrame
time_grain: Granularity (P1D, PT1H, etc.)
time_col: Datetime column name
Returns:
DataFrame aggregated to specified granularity
"""
@staticmethod
def post_process(df: pd.DataFrame,
form_data: Dict[str, Any]) -> pd.DataFrame:
"""
Apply post-processing operations to DataFrame.
Args:
df: Processed DataFrame
form_data: Chart configuration
Returns:
Post-processed DataFrame
"""
def df_to_records(df: pd.DataFrame) -> List[Dict[str, Any]]:
"""Convert DataFrame to list of records."""
def apply_row_limit(df: pd.DataFrame, limit: int) -> pd.DataFrame:
"""Apply row limit to DataFrame."""
def apply_filters(df: pd.DataFrame,
filters: List[Dict[str, Any]]) -> pd.DataFrame:
"""Apply filter conditions to DataFrame."""Architecture for creating custom chart types and visualizations.
class VizPlugin:
"""Base class for visualization plugins."""
viz_type: str # Unique identifier
verbose_name: str # Display name
category: str = "Other" # Plugin category
@classmethod
def get_viz_class(cls) -> Type[BaseViz]:
"""
Get visualization class for this plugin.
Returns:
BaseViz subclass
"""
@classmethod
def get_form_data_spec(cls) -> Dict[str, Any]:
"""
Get form specification for chart configuration.
Returns:
Form field specifications
"""
@classmethod
def register(cls) -> None:
"""Register plugin with visualization system."""
def load_viz_plugins(plugin_dir: str) -> None:
"""
Load visualization plugins from directory.
Args:
plugin_dir: Directory containing plugin modules
"""
def register_viz_type(viz_type: str, viz_class: Type[BaseViz]) -> None:
"""
Register new visualization type.
Args:
viz_type: Unique chart type identifier
viz_class: Visualization implementation class
"""Usage Examples:
# Create custom visualization
class MyCustomViz(BaseViz):
viz_type = "my_custom"
verbose_name = "My Custom Chart"
def get_data(self, df):
# Custom data processing logic
return {'data': df.to_dict('records')}
# Register custom visualization
register_viz_type("my_custom", MyCustomViz)
# Use visualization in chart
viz = get_viz("my_custom", datasource, form_data)
chart_data = viz.get_json_data()# Common form data fields across chart types
FormData = {
'datasource': str, # Datasource identifier
'viz_type': str, # Chart type
'metrics': List[str], # Metrics to display
'groupby': List[str], # Grouping columns
'time_grain_sqla': str, # Time granularity
'since': str, # Start time
'until': str, # End time
'filters': List[Dict], # Filter conditions
'row_limit': int, # Row limit
'order_desc': bool, # Sort order
'color_scheme': str, # Color palette
'show_legend': bool, # Show/hide legend
'rich_tooltip': bool, # Enhanced tooltips
'y_axis_format': str, # Y-axis number format
}Install with Tessl CLI
npx tessl i tessl/pypi-apache-superset@1.0.1