vizforge 0.1.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.
vizforge/__init__.py ADDED
@@ -0,0 +1,48 @@
1
+ """
2
+ VizForge - Production-grade data visualization library with zero AI dependencies.
3
+
4
+ Create beautiful, interactive visualizations with a single line of code.
5
+ """
6
+
7
+ from .core import (
8
+ BaseChart,
9
+ Theme,
10
+ get_theme,
11
+ set_theme,
12
+ register_theme,
13
+ list_themes,
14
+ )
15
+
16
+ from .charts import (
17
+ LineChart,
18
+ line,
19
+ BarChart,
20
+ bar,
21
+ ScatterPlot,
22
+ scatter,
23
+ PieChart,
24
+ pie,
25
+ donut,
26
+ )
27
+
28
+ __version__ = "0.1.0"
29
+
30
+ __all__ = [
31
+ # Core
32
+ "BaseChart",
33
+ "Theme",
34
+ "get_theme",
35
+ "set_theme",
36
+ "register_theme",
37
+ "list_themes",
38
+ # Charts
39
+ "LineChart",
40
+ "line",
41
+ "BarChart",
42
+ "bar",
43
+ "ScatterPlot",
44
+ "scatter",
45
+ "PieChart",
46
+ "pie",
47
+ "donut",
48
+ ]
@@ -0,0 +1,18 @@
1
+ """VizForge chart types."""
2
+
3
+ from .line import LineChart, line
4
+ from .bar import BarChart, bar
5
+ from .scatter import ScatterPlot, scatter
6
+ from .pie import PieChart, pie, donut
7
+
8
+ __all__ = [
9
+ "LineChart",
10
+ "line",
11
+ "BarChart",
12
+ "bar",
13
+ "ScatterPlot",
14
+ "scatter",
15
+ "PieChart",
16
+ "pie",
17
+ "donut",
18
+ ]
vizforge/charts/bar.py ADDED
@@ -0,0 +1,260 @@
1
+ """Bar chart implementation for VizForge."""
2
+
3
+ from typing import Any, Optional, Union
4
+ import plotly.graph_objects as go
5
+ import pandas as pd
6
+ import numpy as np
7
+
8
+ from ..core.base import BaseChart
9
+ from ..core.theme import Theme
10
+
11
+
12
+ class BarChart(BaseChart):
13
+ """
14
+ Bar chart visualization.
15
+
16
+ Supports vertical and horizontal bars, grouped and stacked layouts.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ data: Optional[Union[pd.DataFrame, dict, list]] = None,
22
+ x: Optional[Union[str, list, np.ndarray]] = None,
23
+ y: Optional[Union[str, list, np.ndarray]] = None,
24
+ title: Optional[str] = None,
25
+ theme: Optional[Union[str, Theme]] = None,
26
+ orientation: str = "v",
27
+ barmode: str = "group",
28
+ color: Optional[Union[str, list]] = None,
29
+ **kwargs
30
+ ):
31
+ """
32
+ Create a bar chart.
33
+
34
+ Args:
35
+ data: Data source (DataFrame, dict, or list)
36
+ x: X-axis data or column name
37
+ y: Y-axis data or column name
38
+ title: Chart title
39
+ theme: Theme name or Theme object
40
+ orientation: 'v' for vertical, 'h' for horizontal
41
+ barmode: 'group', 'stack', 'relative', or 'overlay'
42
+ color: Column name for color grouping or list of colors
43
+ **kwargs: Additional arguments
44
+
45
+ Example:
46
+ >>> bar = BarChart(data=df, x='category', y='value', title='Sales by Category')
47
+ >>> bar.show()
48
+ """
49
+ super().__init__(title=title, theme=theme, **kwargs)
50
+ self.orientation = orientation
51
+ self.barmode = barmode
52
+ self.color = color
53
+
54
+ if data is not None:
55
+ self.plot(data, x, y)
56
+
57
+ def plot(
58
+ self,
59
+ data: Union[pd.DataFrame, dict, list],
60
+ x: Optional[Union[str, list, np.ndarray]] = None,
61
+ y: Optional[Union[str, list, np.ndarray]] = None,
62
+ name: Optional[str] = None,
63
+ **kwargs
64
+ ) -> 'BarChart':
65
+ """
66
+ Plot data on the chart.
67
+
68
+ Args:
69
+ data: Data source
70
+ x: X-axis data or column name
71
+ y: Y-axis data or column name
72
+ name: Series name
73
+ **kwargs: Additional trace arguments
74
+
75
+ Returns:
76
+ Self for method chaining
77
+ """
78
+ # Create figure if not exists
79
+ if self.fig is None:
80
+ self.fig = self._create_figure()
81
+ self.fig.update_layout(barmode=self.barmode)
82
+
83
+ # Parse data
84
+ if self.color and isinstance(data, pd.DataFrame) and isinstance(self.color, str):
85
+ # Grouped bars by color column
86
+ self._plot_grouped(data, x, y, self.color, **kwargs)
87
+ else:
88
+ # Simple bar chart
89
+ x_data, y_data_list, names = self._parse_data(data, x, y, name)
90
+
91
+ for y_data, trace_name in zip(y_data_list, names):
92
+ if self.orientation == "v":
93
+ self.fig.add_trace(
94
+ go.Bar(
95
+ x=x_data,
96
+ y=y_data,
97
+ name=trace_name,
98
+ **kwargs
99
+ )
100
+ )
101
+ else:
102
+ self.fig.add_trace(
103
+ go.Bar(
104
+ x=y_data,
105
+ y=x_data,
106
+ name=trace_name,
107
+ orientation='h',
108
+ **kwargs
109
+ )
110
+ )
111
+
112
+ return self
113
+
114
+ def _plot_grouped(
115
+ self,
116
+ data: pd.DataFrame,
117
+ x: str,
118
+ y: str,
119
+ color: str,
120
+ **kwargs
121
+ ) -> None:
122
+ """Plot grouped bars by color column."""
123
+ groups = data[color].unique()
124
+
125
+ for group in groups:
126
+ group_data = data[data[color] == group]
127
+
128
+ if self.orientation == "v":
129
+ self.fig.add_trace(
130
+ go.Bar(
131
+ x=group_data[x],
132
+ y=group_data[y],
133
+ name=str(group),
134
+ **kwargs
135
+ )
136
+ )
137
+ else:
138
+ self.fig.add_trace(
139
+ go.Bar(
140
+ x=group_data[y],
141
+ y=group_data[x],
142
+ name=str(group),
143
+ orientation='h',
144
+ **kwargs
145
+ )
146
+ )
147
+
148
+ def _parse_data(
149
+ self,
150
+ data: Union[pd.DataFrame, dict, list],
151
+ x: Optional[Union[str, list, np.ndarray]],
152
+ y: Optional[Union[str, list, np.ndarray]],
153
+ name: Optional[str]
154
+ ) -> tuple[Any, list[Any], list[str]]:
155
+ """Parse different data formats into x, y, and names."""
156
+
157
+ # Handle DataFrame
158
+ if isinstance(data, pd.DataFrame):
159
+ if isinstance(x, str):
160
+ x_data = data[x].values
161
+ elif x is None:
162
+ x_data = data.index.values
163
+ else:
164
+ x_data = x
165
+
166
+ if isinstance(y, str):
167
+ y_data_list = [data[y].values]
168
+ names = [name or y]
169
+ elif isinstance(y, list) and all(isinstance(col, str) for col in y):
170
+ # Multiple y columns
171
+ y_data_list = [data[col].values for col in y]
172
+ names = y if name is None else [f"{name} - {col}" for col in y]
173
+ else:
174
+ y_data_list = [y]
175
+ names = [name or "trace"]
176
+
177
+ return x_data, y_data_list, names
178
+
179
+ # Handle dict
180
+ elif isinstance(data, dict):
181
+ if isinstance(x, str):
182
+ x_data = data[x]
183
+ else:
184
+ x_data = x
185
+
186
+ if isinstance(y, str):
187
+ y_data_list = [data[y]]
188
+ names = [name or y]
189
+ elif isinstance(y, list) and all(isinstance(col, str) for col in y):
190
+ y_data_list = [data[col] for col in y]
191
+ names = y if name is None else [f"{name} - {col}" for col in y]
192
+ else:
193
+ y_data_list = [y]
194
+ names = [name or "trace"]
195
+
196
+ return x_data, y_data_list, names
197
+
198
+ # Handle arrays/lists
199
+ else:
200
+ x_data = x
201
+ y_data_list = [y]
202
+ names = [name or "trace"]
203
+ return x_data, y_data_list, names
204
+
205
+
206
+ def bar(
207
+ data: Union[pd.DataFrame, dict, list],
208
+ x: Optional[Union[str, list, np.ndarray]] = None,
209
+ y: Optional[Union[str, list, np.ndarray]] = None,
210
+ title: Optional[str] = None,
211
+ theme: Optional[Union[str, Theme]] = None,
212
+ orientation: str = "v",
213
+ barmode: str = "group",
214
+ color: Optional[Union[str, list]] = None,
215
+ show: bool = True,
216
+ export: Optional[str] = None,
217
+ **kwargs
218
+ ) -> BarChart:
219
+ """
220
+ Create and display a bar chart (convenience function).
221
+
222
+ Args:
223
+ data: Data source (DataFrame, dict, or list)
224
+ x: X-axis data or column name
225
+ y: Y-axis data or column name
226
+ title: Chart title
227
+ theme: Theme name or Theme object
228
+ orientation: 'v' for vertical, 'h' for horizontal
229
+ barmode: 'group', 'stack', 'relative', or 'overlay'
230
+ color: Column name for color grouping
231
+ show: Whether to display the chart
232
+ export: Export filename (optional)
233
+ **kwargs: Additional arguments
234
+
235
+ Returns:
236
+ BarChart object
237
+
238
+ Example:
239
+ >>> bar(df, x='category', y='value', title='Sales by Category')
240
+ >>> bar(df, x='month', y='revenue', color='region', barmode='stack')
241
+ """
242
+ chart = BarChart(
243
+ data=data,
244
+ x=x,
245
+ y=y,
246
+ title=title,
247
+ theme=theme,
248
+ orientation=orientation,
249
+ barmode=barmode,
250
+ color=color,
251
+ **kwargs
252
+ )
253
+
254
+ if export:
255
+ chart.export(export)
256
+
257
+ if show:
258
+ chart.show()
259
+
260
+ return chart
@@ -0,0 +1,217 @@
1
+ """Line chart implementation for VizForge."""
2
+
3
+ from typing import Any, Optional, Union
4
+ import plotly.graph_objects as go
5
+ import pandas as pd
6
+ import numpy as np
7
+
8
+ from ..core.base import BaseChart
9
+ from ..core.theme import Theme
10
+
11
+
12
+ class LineChart(BaseChart):
13
+ """
14
+ Line chart visualization.
15
+
16
+ Supports single and multi-line charts, area charts, and step charts.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ data: Optional[Union[pd.DataFrame, dict, list]] = None,
22
+ x: Optional[Union[str, list, np.ndarray]] = None,
23
+ y: Optional[Union[str, list, np.ndarray]] = None,
24
+ title: Optional[str] = None,
25
+ theme: Optional[Union[str, Theme]] = None,
26
+ mode: str = "lines",
27
+ fill: Optional[str] = None,
28
+ **kwargs
29
+ ):
30
+ """
31
+ Create a line chart.
32
+
33
+ Args:
34
+ data: Data source (DataFrame, dict, or list)
35
+ x: X-axis data or column name
36
+ y: Y-axis data or column name (can be list of columns for multi-line)
37
+ title: Chart title
38
+ theme: Theme name or Theme object
39
+ mode: Display mode ('lines', 'markers', 'lines+markers')
40
+ fill: Fill area ('none', 'tozeroy', 'tonexty')
41
+ **kwargs: Additional arguments
42
+
43
+ Example:
44
+ >>> line = LineChart(data=df, x='date', y='sales', title='Sales Trend')
45
+ >>> line.show()
46
+ """
47
+ super().__init__(title=title, theme=theme, **kwargs)
48
+ self.mode = mode
49
+ self.fill = fill
50
+
51
+ if data is not None:
52
+ self.plot(data, x, y)
53
+
54
+ def plot(
55
+ self,
56
+ data: Union[pd.DataFrame, dict, list],
57
+ x: Optional[Union[str, list, np.ndarray]] = None,
58
+ y: Optional[Union[str, list, np.ndarray]] = None,
59
+ name: Optional[str] = None,
60
+ **kwargs
61
+ ) -> 'LineChart':
62
+ """
63
+ Plot data on the chart.
64
+
65
+ Args:
66
+ data: Data source
67
+ x: X-axis data or column name
68
+ y: Y-axis data or column name
69
+ name: Series name
70
+ **kwargs: Additional trace arguments
71
+
72
+ Returns:
73
+ Self for method chaining
74
+ """
75
+ # Create figure if not exists
76
+ if self.fig is None:
77
+ self.fig = self._create_figure()
78
+
79
+ # Parse data
80
+ x_data, y_data_list, names = self._parse_data(data, x, y, name)
81
+
82
+ # Add traces
83
+ for y_data, trace_name in zip(y_data_list, names):
84
+ trace_kwargs = {
85
+ 'mode': self.mode,
86
+ 'line': {'width': self._theme.line_width},
87
+ 'marker': {'size': self._theme.marker_size},
88
+ }
89
+
90
+ if self.fill:
91
+ trace_kwargs['fill'] = self.fill
92
+
93
+ trace_kwargs.update(kwargs)
94
+
95
+ self.fig.add_trace(
96
+ go.Scatter(
97
+ x=x_data,
98
+ y=y_data,
99
+ name=trace_name,
100
+ **trace_kwargs
101
+ )
102
+ )
103
+
104
+ return self
105
+
106
+ def _parse_data(
107
+ self,
108
+ data: Union[pd.DataFrame, dict, list],
109
+ x: Optional[Union[str, list, np.ndarray]],
110
+ y: Optional[Union[str, list, np.ndarray]],
111
+ name: Optional[str]
112
+ ) -> tuple[Any, list[Any], list[str]]:
113
+ """Parse different data formats into x, y, and names."""
114
+
115
+ # Handle DataFrame
116
+ if isinstance(data, pd.DataFrame):
117
+ if isinstance(x, str):
118
+ x_data = data[x].values
119
+ elif x is None:
120
+ x_data = data.index.values
121
+ else:
122
+ x_data = x
123
+
124
+ if isinstance(y, str):
125
+ y_data_list = [data[y].values]
126
+ names = [name or y]
127
+ elif isinstance(y, list) and all(isinstance(col, str) for col in y):
128
+ # Multiple y columns
129
+ y_data_list = [data[col].values for col in y]
130
+ names = y if name is None else [f"{name} - {col}" for col in y]
131
+ else:
132
+ y_data_list = [y]
133
+ names = [name or "trace"]
134
+
135
+ return x_data, y_data_list, names
136
+
137
+ # Handle dict
138
+ elif isinstance(data, dict):
139
+ if x is None:
140
+ x_data = list(range(len(next(iter(data.values())))))
141
+ elif isinstance(x, str):
142
+ x_data = data[x]
143
+ else:
144
+ x_data = x
145
+
146
+ if isinstance(y, str):
147
+ y_data_list = [data[y]]
148
+ names = [name or y]
149
+ elif isinstance(y, list) and all(isinstance(col, str) for col in y):
150
+ y_data_list = [data[col] for col in y]
151
+ names = y if name is None else [f"{name} - {col}" for col in y]
152
+ else:
153
+ y_data_list = [y]
154
+ names = [name or "trace"]
155
+
156
+ return x_data, y_data_list, names
157
+
158
+ # Handle arrays/lists
159
+ else:
160
+ x_data = x if x is not None else list(range(len(y)))
161
+ y_data_list = [y]
162
+ names = [name or "trace"]
163
+ return x_data, y_data_list, names
164
+
165
+
166
+ def line(
167
+ data: Union[pd.DataFrame, dict, list],
168
+ x: Optional[Union[str, list, np.ndarray]] = None,
169
+ y: Optional[Union[str, list, np.ndarray]] = None,
170
+ title: Optional[str] = None,
171
+ theme: Optional[Union[str, Theme]] = None,
172
+ mode: str = "lines",
173
+ fill: Optional[str] = None,
174
+ show: bool = True,
175
+ export: Optional[str] = None,
176
+ **kwargs
177
+ ) -> LineChart:
178
+ """
179
+ Create and display a line chart (convenience function).
180
+
181
+ Args:
182
+ data: Data source (DataFrame, dict, or list)
183
+ x: X-axis data or column name
184
+ y: Y-axis data or column name
185
+ title: Chart title
186
+ theme: Theme name or Theme object
187
+ mode: Display mode ('lines', 'markers', 'lines+markers')
188
+ fill: Fill area ('none', 'tozeroy', 'tonexty')
189
+ show: Whether to display the chart
190
+ export: Export filename (optional)
191
+ **kwargs: Additional arguments
192
+
193
+ Returns:
194
+ LineChart object
195
+
196
+ Example:
197
+ >>> line(df, x='date', y='sales', title='Sales Trend')
198
+ >>> line(df, x='date', y=['sales', 'profit'], theme='dark')
199
+ """
200
+ chart = LineChart(
201
+ data=data,
202
+ x=x,
203
+ y=y,
204
+ title=title,
205
+ theme=theme,
206
+ mode=mode,
207
+ fill=fill,
208
+ **kwargs
209
+ )
210
+
211
+ if export:
212
+ chart.export(export)
213
+
214
+ if show:
215
+ chart.show()
216
+
217
+ return chart