bidviz 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bidviz/__init__.py ADDED
@@ -0,0 +1,14 @@
1
+ """
2
+ BidViz - Backend Visualization Data Transformation Library
3
+
4
+ A powerful, configurable backend visualization data transformation library designed to bridge
5
+ the gap between raw data and frontend charting libraries.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+ __author__ = "Mohammad Amin Khara"
10
+
11
+ from bidviz.exceptions import TransformationError, ValidationError
12
+ from bidviz.transformer import ChartTransformer
13
+
14
+ __all__ = ["ChartTransformer", "TransformationError", "ValidationError"]
@@ -0,0 +1,5 @@
1
+ """Core module initialization."""
2
+
3
+ from bidviz.core.base import BaseChartTransformer
4
+
5
+ __all__ = ["BaseChartTransformer"]
bidviz/core/base.py ADDED
@@ -0,0 +1,43 @@
1
+ """Base transformer class for all chart transformations."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ import pandas as pd
6
+
7
+
8
+ class BaseChartTransformer:
9
+ """
10
+ Base class for chart transformers.
11
+
12
+ All specific chart transformers should inherit from this class
13
+ and implement the transform method.
14
+ """
15
+
16
+ def transform(self, df: pd.DataFrame, **kwargs: Any) -> Dict[str, Any]:
17
+ """
18
+ Transform a DataFrame into chart-ready format.
19
+
20
+ Args:
21
+ df: Input DataFrame
22
+ **kwargs: Additional transformation parameters
23
+
24
+ Returns:
25
+ Dictionary containing chart data and metadata
26
+
27
+ Raises:
28
+ NotImplementedError: If not implemented by subclass
29
+ """
30
+ raise NotImplementedError("Subclasses must implement transform method")
31
+
32
+ def _validate_dataframe(self, df: pd.DataFrame) -> None:
33
+ """
34
+ Validate that DataFrame is not None and has data.
35
+
36
+ Args:
37
+ df: DataFrame to validate
38
+
39
+ Raises:
40
+ ValueError: If DataFrame is None
41
+ """
42
+ if df is None:
43
+ raise ValueError("DataFrame cannot be None")
bidviz/exceptions.py ADDED
@@ -0,0 +1,69 @@
1
+ """
2
+ Custom exceptions for BidViz library.
3
+ """
4
+
5
+
6
+ class BidVizError(Exception):
7
+ """Base exception for all BidViz errors."""
8
+
9
+ pass
10
+
11
+
12
+ class TransformationError(BidVizError):
13
+ """
14
+ Exception raised when data transformation fails.
15
+
16
+ Attributes:
17
+ message (str): Explanation of the error
18
+ chart_type (str): Type of chart being transformed
19
+ df_shape (tuple): Shape of the DataFrame (rows, columns)
20
+ missing_columns (list): List of missing column names
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ message: str,
26
+ chart_type: str = None,
27
+ df_shape: tuple = None,
28
+ missing_columns: list = None,
29
+ ):
30
+ self.message = message
31
+ self.chart_type = chart_type
32
+ self.df_shape = df_shape
33
+ self.missing_columns = missing_columns or []
34
+ super().__init__(self.message)
35
+
36
+ def __str__(self) -> str:
37
+ details = [self.message]
38
+ if self.chart_type:
39
+ details.append(f"Chart Type: {self.chart_type}")
40
+ if self.df_shape:
41
+ details.append(f"DataFrame Shape: {self.df_shape}")
42
+ if self.missing_columns:
43
+ details.append(f"Missing Columns: {', '.join(self.missing_columns)}")
44
+ return " | ".join(details)
45
+
46
+
47
+ class ValidationError(BidVizError):
48
+ """
49
+ Exception raised when data validation fails.
50
+
51
+ Attributes:
52
+ message (str): Explanation of the validation error
53
+ column (str): Column name that failed validation
54
+ validation_type (str): Type of validation that failed
55
+ """
56
+
57
+ def __init__(self, message: str, column: str = None, validation_type: str = None):
58
+ self.message = message
59
+ self.column = column
60
+ self.validation_type = validation_type
61
+ super().__init__(self.message)
62
+
63
+ def __str__(self) -> str:
64
+ details = [self.message]
65
+ if self.column:
66
+ details.append(f"Column: {self.column}")
67
+ if self.validation_type:
68
+ details.append(f"Validation Type: {self.validation_type}")
69
+ return " | ".join(details)
bidviz/transformer.py ADDED
@@ -0,0 +1,312 @@
1
+ """
2
+ Core chart transformation service - facade for all chart transformers.
3
+ """
4
+
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ import pandas as pd
8
+
9
+ from bidviz.transformers import (
10
+ BarChartTransformer,
11
+ CorrelationHeatmapTransformer,
12
+ DataTableTransformer,
13
+ FunnelChartTransformer,
14
+ HeatmapTransformer,
15
+ KPICardsTransformer,
16
+ LineChartTransformer,
17
+ MultiLineChartTransformer,
18
+ PieChartTransformer,
19
+ StackedBarChartTransformer,
20
+ )
21
+
22
+
23
+ class ChartTransformer:
24
+ """
25
+ Main facade for transforming pandas DataFrames into chart-ready data structures.
26
+
27
+ This class provides a unified interface to all chart transformers,
28
+ converting raw DataFrames into JSON-serializable formats optimized
29
+ for various charting libraries (Chart.js, D3, Plotly, Recharts, etc.).
30
+
31
+ The actual transformation logic is delegated to specialized transformer
32
+ classes for maintainability and modularity.
33
+
34
+ Supported chart types:
35
+ - KPI Cards
36
+ - Bar Chart
37
+ - Line Chart
38
+ - Multi-Line Chart
39
+ - Pie Chart
40
+ - Heatmap
41
+ - Funnel Chart
42
+ - Stacked Bar Chart
43
+ - Data Table (with pagination)
44
+ - Correlation Heatmap
45
+
46
+ Examples:
47
+ >>> transformer = ChartTransformer()
48
+ >>> df = pd.DataFrame({'vendor': ['A', 'B'], 'revenue': [100, 200]})
49
+ >>> result = transformer.transform_to_bar_chart(df, 'vendor', 'revenue')
50
+ >>> result['chart_type']
51
+ 'bar_chart'
52
+ """
53
+
54
+ def __init__(self) -> None:
55
+ """Initialize the chart transformer with all specialized transformers."""
56
+ self._kpi_transformer = KPICardsTransformer()
57
+ self._bar_transformer = BarChartTransformer()
58
+ self._line_transformer = LineChartTransformer()
59
+ self._multi_line_transformer = MultiLineChartTransformer()
60
+ self._pie_transformer = PieChartTransformer()
61
+ self._heatmap_transformer = HeatmapTransformer()
62
+ self._funnel_transformer = FunnelChartTransformer()
63
+ self._stacked_bar_transformer = StackedBarChartTransformer()
64
+ self._table_transformer = DataTableTransformer()
65
+ self._correlation_transformer = CorrelationHeatmapTransformer()
66
+
67
+ def transform_to_kpi_cards(self, df: pd.DataFrame) -> Dict[str, Any]:
68
+ """
69
+ Transform a single-row DataFrame into KPI cards for dashboard metrics.
70
+
71
+ Args:
72
+ df: Single-row DataFrame containing metrics
73
+
74
+ Returns:
75
+ Dict with chart_type='kpi_cards' and list of card data
76
+
77
+ Raises:
78
+ TransformationError: If DataFrame has more than one row
79
+
80
+ Examples:
81
+ >>> df = pd.DataFrame({'total_orders': [150], 'revenue': [45000.50]})
82
+ >>> result = transformer.transform_to_kpi_cards(df)
83
+ >>> len(result['data'])
84
+ 2
85
+ """
86
+ return self._kpi_transformer.transform(df)
87
+
88
+ def transform_to_bar_chart(
89
+ self,
90
+ df: pd.DataFrame,
91
+ x_column: str,
92
+ y_column: str,
93
+ label_column: Optional[str] = None,
94
+ ) -> Dict[str, Any]:
95
+ """
96
+ Transform DataFrame into bar chart data structure.
97
+
98
+ Args:
99
+ df: DataFrame containing the data
100
+ x_column: Column name for x-axis (categorical)
101
+ y_column: Column name for y-axis (numeric)
102
+ label_column: Optional column for custom labels
103
+
104
+ Returns:
105
+ Dict with chart_type='bar_chart', data points, and axis labels
106
+
107
+ Examples:
108
+ >>> df = pd.DataFrame({'vendor': ['A', 'B'], 'revenue': [1000, 1500]})
109
+ >>> result = transformer.transform_to_bar_chart(df, 'vendor', 'revenue')
110
+ >>> result['chart_type']
111
+ 'bar_chart'
112
+ """
113
+ return self._bar_transformer.transform(df, x_column, y_column, label_column)
114
+
115
+ def transform_to_line_chart(
116
+ self,
117
+ df: pd.DataFrame,
118
+ x_column: str,
119
+ y_column: str,
120
+ series_name: Optional[str] = None,
121
+ ) -> Dict[str, Any]:
122
+ """
123
+ Transform DataFrame into line chart data for time series or trends.
124
+
125
+ Args:
126
+ df: DataFrame containing the data
127
+ x_column: Column name for x-axis
128
+ y_column: Column name for y-axis
129
+ series_name: Optional custom name for the data series
130
+
131
+ Returns:
132
+ Dict with chart_type='line_chart', data points, and labels
133
+
134
+ Examples:
135
+ >>> df = pd.DataFrame({'date': pd.date_range('2024-01-01', periods=3),
136
+ ... 'orders': [10, 15, 12]})
137
+ >>> result = transformer.transform_to_line_chart(df, 'date', 'orders')
138
+ >>> result['series_name']
139
+ 'Orders'
140
+ """
141
+ return self._line_transformer.transform(df, x_column, y_column, series_name)
142
+
143
+ def transform_to_multi_line_chart(
144
+ self,
145
+ df: pd.DataFrame,
146
+ x_column: str,
147
+ y_columns: List[str],
148
+ series_names: Optional[List[str]] = None,
149
+ ) -> Dict[str, Any]:
150
+ """
151
+ Transform DataFrame into multi-line chart for comparing multiple series.
152
+
153
+ Args:
154
+ df: DataFrame containing the data
155
+ x_column: Column name for x-axis
156
+ y_columns: List of column names for y-axis
157
+ series_names: Optional custom names for each series
158
+
159
+ Returns:
160
+ Dict with chart_type='multi_line_chart' and series data
161
+
162
+ Examples:
163
+ >>> df = pd.DataFrame({'date': ['2024-01-01', '2024-01-02'],
164
+ ... 'vendor_a': [10, 15], 'vendor_b': [12, 18]})
165
+ >>> result = transformer.transform_to_multi_line_chart(
166
+ ... df, 'date', ['vendor_a', 'vendor_b'])
167
+ >>> len(result['series'])
168
+ 2
169
+ """
170
+ return self._multi_line_transformer.transform(df, x_column, y_columns, series_names)
171
+
172
+ def transform_to_pie_chart(
173
+ self, df: pd.DataFrame, label_column: str, value_column: str
174
+ ) -> Dict[str, Any]:
175
+ """
176
+ Transform DataFrame into pie chart data for part-to-whole relationships.
177
+
178
+ Args:
179
+ df: DataFrame containing the data
180
+ label_column: Column name for slice labels
181
+ value_column: Column name for slice values
182
+
183
+ Returns:
184
+ Dict with chart_type='pie_chart' and data points
185
+
186
+ Examples:
187
+ >>> df = pd.DataFrame({'category': ['A', 'B'], 'sales': [45000, 32000]})
188
+ >>> result = transformer.transform_to_pie_chart(df, 'category', 'sales')
189
+ >>> len(result['data'])
190
+ 2
191
+ """
192
+ return self._pie_transformer.transform(df, label_column, value_column)
193
+
194
+ def transform_to_heatmap(
195
+ self, df: pd.DataFrame, x_column: str, y_column: str, value_column: str
196
+ ) -> Dict[str, Any]:
197
+ """
198
+ Transform DataFrame into heatmap data for 2D intensity visualization.
199
+
200
+ Args:
201
+ df: DataFrame containing the data
202
+ x_column: Column name for x-axis
203
+ y_column: Column name for y-axis
204
+ value_column: Column name for cell values
205
+
206
+ Returns:
207
+ Dict with chart_type='heatmap', data points, and labels
208
+
209
+ Examples:
210
+ >>> df = pd.DataFrame({'hour': [0, 1], 'day': ['Mon', 'Mon'],
211
+ ... 'count': [12, 8]})
212
+ >>> result = transformer.transform_to_heatmap(df, 'hour', 'day', 'count')
213
+ >>> result['chart_type']
214
+ 'heatmap'
215
+ """
216
+ return self._heatmap_transformer.transform(df, x_column, y_column, value_column)
217
+
218
+ def transform_to_funnel_chart(
219
+ self, df: pd.DataFrame, stage_column: str, value_column: str
220
+ ) -> Dict[str, Any]:
221
+ """
222
+ Transform DataFrame into funnel chart data for conversion pipelines.
223
+
224
+ Args:
225
+ df: DataFrame containing the data
226
+ stage_column: Column name for funnel stages
227
+ value_column: Column name for stage values
228
+
229
+ Returns:
230
+ Dict with chart_type='funnel_chart' and data points
231
+
232
+ Examples:
233
+ >>> df = pd.DataFrame({'stage': ['Visits', 'Sign-ups'],
234
+ ... 'count': [1000, 300]})
235
+ >>> result = transformer.transform_to_funnel_chart(df, 'stage', 'count')
236
+ >>> len(result['data'])
237
+ 2
238
+ """
239
+ return self._funnel_transformer.transform(df, stage_column, value_column)
240
+
241
+ def transform_to_stacked_bar_chart(
242
+ self,
243
+ df: pd.DataFrame,
244
+ x_column: str,
245
+ y_columns: List[str],
246
+ category_names: Optional[List[str]] = None,
247
+ ) -> Dict[str, Any]:
248
+ """
249
+ Transform DataFrame into stacked bar chart for composed comparisons.
250
+
251
+ Args:
252
+ df: DataFrame containing the data
253
+ x_column: Column name for x-axis
254
+ y_columns: List of column names for stacked values
255
+ category_names: Optional custom names for each stack
256
+
257
+ Returns:
258
+ Dict with chart_type='stacked_bar_chart' and data
259
+
260
+ Examples:
261
+ >>> df = pd.DataFrame({'month': ['Jan', 'Feb'],
262
+ ... 'product_a': [100, 150], 'product_b': [200, 180]})
263
+ >>> result = transformer.transform_to_stacked_bar_chart(
264
+ ... df, 'month', ['product_a', 'product_b'])
265
+ >>> len(result['categories'])
266
+ 2
267
+ """
268
+ return self._stacked_bar_transformer.transform(df, x_column, y_columns, category_names)
269
+
270
+ def transform_to_data_table(
271
+ self, df: pd.DataFrame, page: int = 1, page_size: int = 50
272
+ ) -> Dict[str, Any]:
273
+ """
274
+ Transform DataFrame into paginated data table structure.
275
+
276
+ Args:
277
+ df: DataFrame containing the data
278
+ page: Page number (1-indexed)
279
+ page_size: Number of rows per page
280
+
281
+ Returns:
282
+ Dict with chart_type='data_table', columns, rows, and pagination
283
+
284
+ Examples:
285
+ >>> df = pd.DataFrame({'id': [1, 2, 3], 'name': ['A', 'B', 'C']})
286
+ >>> result = transformer.transform_to_data_table(df, page=1, page_size=2)
287
+ >>> len(result['rows'])
288
+ 2
289
+ """
290
+ return self._table_transformer.transform(df, page, page_size)
291
+
292
+ def transform_to_correlation_heatmap(
293
+ self, df: pd.DataFrame, metrics: Optional[List[str]] = None
294
+ ) -> Dict[str, Any]:
295
+ """
296
+ Transform DataFrame into correlation heatmap for statistical analysis.
297
+
298
+ Args:
299
+ df: DataFrame containing numeric columns
300
+ metrics: Optional list of column names to correlate
301
+
302
+ Returns:
303
+ Dict with chart_type='heatmap' and correlation data
304
+
305
+ Examples:
306
+ >>> df = pd.DataFrame({'revenue': [100, 200, 150],
307
+ ... 'orders': [10, 20, 15]})
308
+ >>> result = transformer.transform_to_correlation_heatmap(df)
309
+ >>> result['chart_type']
310
+ 'heatmap'
311
+ """
312
+ return self._correlation_transformer.transform(df, metrics)
@@ -0,0 +1,22 @@
1
+ """Transformers module initialization."""
2
+
3
+ from bidviz.transformers.bar import BarChartTransformer
4
+ from bidviz.transformers.heatmap import CorrelationHeatmapTransformer, HeatmapTransformer
5
+ from bidviz.transformers.kpi import KPICardsTransformer
6
+ from bidviz.transformers.line import LineChartTransformer, MultiLineChartTransformer
7
+ from bidviz.transformers.other import FunnelChartTransformer, StackedBarChartTransformer
8
+ from bidviz.transformers.pie import PieChartTransformer
9
+ from bidviz.transformers.table import DataTableTransformer
10
+
11
+ __all__ = [
12
+ "KPICardsTransformer",
13
+ "BarChartTransformer",
14
+ "LineChartTransformer",
15
+ "MultiLineChartTransformer",
16
+ "PieChartTransformer",
17
+ "HeatmapTransformer",
18
+ "FunnelChartTransformer",
19
+ "StackedBarChartTransformer",
20
+ "DataTableTransformer",
21
+ "CorrelationHeatmapTransformer",
22
+ ]
@@ -0,0 +1,68 @@
1
+ """Bar chart transformer."""
2
+
3
+ from typing import Any, Dict, Optional
4
+
5
+ import pandas as pd
6
+
7
+ from bidviz.core.base import BaseChartTransformer
8
+ from bidviz.exceptions import TransformationError
9
+ from bidviz.utils import format_label, safe_get_value, validate_columns
10
+
11
+
12
+ class BarChartTransformer(BaseChartTransformer):
13
+ """Transform DataFrame into bar chart data."""
14
+
15
+ def transform(
16
+ self,
17
+ df: pd.DataFrame,
18
+ x_column: str,
19
+ y_column: str,
20
+ label_column: Optional[str] = None,
21
+ ) -> Dict[str, Any]:
22
+ """
23
+ Transform DataFrame into bar chart data structure.
24
+
25
+ Args:
26
+ df: DataFrame containing the data
27
+ x_column: Column name for x-axis (categorical)
28
+ y_column: Column name for y-axis (numeric)
29
+ label_column: Optional column for custom labels
30
+
31
+ Returns:
32
+ Dict with chart_type='bar_chart', data points, and axis labels
33
+
34
+ Raises:
35
+ TransformationError: If required columns are missing
36
+ """
37
+ try:
38
+ validate_columns(df, [x_column, y_column])
39
+ if label_column:
40
+ validate_columns(df, [label_column])
41
+ else:
42
+ label_column = x_column
43
+
44
+ data = []
45
+ for _, row in df.iterrows():
46
+ data.append(
47
+ {
48
+ "x": str(safe_get_value(row[x_column])),
49
+ "y": safe_get_value(row[y_column]),
50
+ "label": str(safe_get_value(row[label_column])),
51
+ }
52
+ )
53
+
54
+ return {
55
+ "chart_type": "bar_chart",
56
+ "data": data,
57
+ "x_label": format_label(x_column),
58
+ "y_label": format_label(y_column),
59
+ }
60
+
61
+ except ValueError as e:
62
+ raise TransformationError(str(e), chart_type="bar_chart", df_shape=df.shape)
63
+ except Exception as e:
64
+ raise TransformationError(
65
+ f"Failed to transform bar chart: {str(e)}",
66
+ chart_type="bar_chart",
67
+ df_shape=df.shape,
68
+ )
@@ -0,0 +1,116 @@
1
+ """Heatmap transformers."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ import pandas as pd
6
+
7
+ from bidviz.core.base import BaseChartTransformer
8
+ from bidviz.exceptions import TransformationError
9
+ from bidviz.utils import format_label, get_numeric_columns, safe_get_value, validate_columns
10
+
11
+
12
+ class HeatmapTransformer(BaseChartTransformer):
13
+ """Transform DataFrame into heatmap data."""
14
+
15
+ def transform(
16
+ self, df: pd.DataFrame, x_column: str, y_column: str, value_column: str
17
+ ) -> Dict[str, Any]:
18
+ """
19
+ Transform DataFrame into heatmap data for 2D intensity visualization.
20
+
21
+ Args:
22
+ df: DataFrame containing the data
23
+ x_column: Column name for x-axis
24
+ y_column: Column name for y-axis
25
+ value_column: Column name for cell values
26
+
27
+ Returns:
28
+ Dict with chart_type='heatmap', data points, and labels
29
+ """
30
+ try:
31
+ validate_columns(df, [x_column, y_column, value_column])
32
+
33
+ data = []
34
+ for _, row in df.iterrows():
35
+ data.append(
36
+ {
37
+ "x": str(safe_get_value(row[x_column])),
38
+ "y": str(safe_get_value(row[y_column])),
39
+ "value": safe_get_value(row[value_column]),
40
+ }
41
+ )
42
+
43
+ return {
44
+ "chart_type": "heatmap",
45
+ "data": data,
46
+ "x_label": format_label(x_column),
47
+ "y_label": format_label(y_column),
48
+ "value_label": format_label(value_column),
49
+ }
50
+
51
+ except ValueError as e:
52
+ raise TransformationError(str(e), chart_type="heatmap", df_shape=df.shape)
53
+ except Exception as e:
54
+ raise TransformationError(
55
+ f"Failed to transform heatmap: {str(e)}",
56
+ chart_type="heatmap",
57
+ df_shape=df.shape,
58
+ )
59
+
60
+
61
+ class CorrelationHeatmapTransformer(BaseChartTransformer):
62
+ """Transform DataFrame into correlation heatmap."""
63
+
64
+ def transform(self, df: pd.DataFrame, metrics: Optional[List[str]] = None) -> Dict[str, Any]:
65
+ """
66
+ Transform DataFrame into correlation heatmap for statistical analysis.
67
+
68
+ Args:
69
+ df: DataFrame containing numeric columns
70
+ metrics: Optional list of column names to correlate
71
+
72
+ Returns:
73
+ Dict with chart_type='heatmap' and correlation data
74
+ """
75
+ try:
76
+ if metrics is None:
77
+ metrics = get_numeric_columns(df)
78
+
79
+ if len(metrics) < 2:
80
+ raise TransformationError(
81
+ "Need at least 2 numeric columns for correlation",
82
+ chart_type="correlation_heatmap",
83
+ df_shape=df.shape,
84
+ )
85
+
86
+ validate_columns(df, metrics)
87
+ corr_matrix = df[metrics].corr()
88
+
89
+ data = []
90
+ for x_metric in metrics:
91
+ for y_metric in metrics:
92
+ data.append(
93
+ {
94
+ "x": x_metric,
95
+ "y": y_metric,
96
+ "value": safe_get_value(corr_matrix.loc[y_metric, x_metric]),
97
+ }
98
+ )
99
+
100
+ return {
101
+ "chart_type": "heatmap",
102
+ "data": data,
103
+ "metrics": metrics,
104
+ "x_label": "Metrics",
105
+ "y_label": "Metrics",
106
+ "value_label": "Correlation Coefficient",
107
+ }
108
+
109
+ except ValueError as e:
110
+ raise TransformationError(str(e), chart_type="correlation_heatmap", df_shape=df.shape)
111
+ except Exception as e:
112
+ raise TransformationError(
113
+ f"Failed to transform correlation heatmap: {str(e)}",
114
+ chart_type="correlation_heatmap",
115
+ df_shape=df.shape,
116
+ )