zaturn 0.1.3__py3-none-any.whl → 0.1.5__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.
zaturn/visualizations.py CHANGED
@@ -1,26 +1,23 @@
1
1
  from fastmcp import FastMCP, Image
2
- import matplotlib.pyplot as plt
2
+ import math
3
3
  import os
4
- import seaborn as sns
4
+ import plotly.express as px
5
5
  import time
6
6
  from typing import Any, Union, Optional
7
7
  from zaturn import config, query_utils
8
8
 
9
- sns.set_theme()
10
9
 
11
10
  mcp = FastMCP("Zaturn Visualizations")
12
11
 
13
12
 
14
- def _plot_to_image(plot) -> Union[str, Image]:
15
- figure = plot.get_figure()
13
+ def _fig_to_image(fig) -> Union[str, Image]:
16
14
  filepath = os.path.join(config.VISUALS_DIR, str(int(time.time())) + '.png')
17
- figure.savefig(filepath)
18
- plt.clf()
15
+ fig.write_image(filepath)
19
16
  if config.RETURN_IMAGES:
20
17
  return Image(path=filepath)
21
18
  else:
22
19
  return filepath
23
-
20
+
24
21
 
25
22
  # Relationships
26
23
 
@@ -29,7 +26,7 @@ def scatter_plot(
29
26
  query_id: str,
30
27
  x: str,
31
28
  y: str,
32
- hue: str = None
29
+ color: str = None
33
30
  ):
34
31
  """
35
32
  Make a scatter plot with the dataframe obtained from running SQL Query against source
@@ -38,11 +35,12 @@ def scatter_plot(
38
35
  query_id: Previously run query to use for plotting
39
36
  x: Column name from SQL result to use for x-axis
40
37
  y: Column name from SQL result to use for y-axis
41
- hue: Optional String; Column name from SQL result to use for coloring the points
38
+ color: Optional; column name from SQL result to use for coloring the points, with color representing another dimension
42
39
  """
43
40
  df = query_utils.load_query(query_id)
44
- plot = sns.scatterplot(df, x=x, y=y, hue=hue)
45
- return _plot_to_image(plot)
41
+ fig = px.scatter(df, x=x, y=y, color=color)
42
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
43
+ return _fig_to_image(fig)
46
44
 
47
45
 
48
46
  @mcp.tool()
@@ -50,7 +48,7 @@ def line_plot(
50
48
  query_id: str,
51
49
  x: str,
52
50
  y: str,
53
- hue: str = None
51
+ color: str = None
54
52
  ):
55
53
  """
56
54
  Make a line plot with the dataframe obtained from running SQL Query against source
@@ -58,11 +56,12 @@ def line_plot(
58
56
  query_id: Previously run query to use for plotting
59
57
  x: Column name from SQL result to use for x-axis
60
58
  y: Column name from SQL result to use for y-axis
61
- hue: Optional; column name from SQL result to use for drawing multiple colored lines
59
+ color: Optional; column name from SQL result to use for drawing multiple colored lines representing another dimension
62
60
  """
63
61
  df = query_utils.load_query(query_id)
64
- plot = sns.lineplot(df, x=x, y=y, hue=hue)
65
- return _plot_to_image(plot)
62
+ fig = px.line(df, x=x, y=y, color=color)
63
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
64
+ return _fig_to_image(fig)
66
65
 
67
66
 
68
67
  # Distributions
@@ -71,21 +70,21 @@ def line_plot(
71
70
  def histogram(
72
71
  query_id: str,
73
72
  column: str,
74
- hue: str = None,
75
- bins: int = None
73
+ color: str = None,
74
+ nbins: int = None
76
75
  ):
77
76
  """
78
77
  Make a histogram with a column of the dataframe obtained from running SQL Query against source
79
78
  Args:
80
79
  query_id: Previously run query to use for plotting
81
80
  column: Column name from SQL result to use for the histogram
82
- hue: Optional; column name from SQL result to use for drawing multiple colored histograms
83
- bins: Optional; number of bins
81
+ color: Optional; column name from SQL result to use for drawing multiple colored histograms representing another dimension
82
+ nbins: Optional; number of bins
84
83
  """
85
84
  df = query_utils.load_query(query_id)
86
- plot = sns.histplot(df, x=column, hue=hue, bins=bins)
87
- return _plot_to_image(plot)
88
-
85
+ fig = px.histogram(df, x=column, color=color, nbins=nbins)
86
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
87
+ return _fig_to_image(fig)
89
88
 
90
89
  # Categorical
91
90
 
@@ -94,8 +93,7 @@ def strip_plot(
94
93
  query_id: str,
95
94
  x: str,
96
95
  y: str = None,
97
- hue: str = None,
98
- legend: bool = False
96
+ color: str = None
99
97
  ):
100
98
  """
101
99
  Make a strip plot with the dataframe obtained from running SQL Query against source
@@ -103,32 +101,33 @@ def strip_plot(
103
101
  query_id: Previously run query to use for plotting
104
102
  x: Column name from SQL result to use for x axis
105
103
  y: Optional; column name from SQL result to use for y axis
106
- hue: Optional; column name from SQL result to use for coloring the points
107
- legend: Whether to draw a legend for the hue
104
+ color: Optional column name from SQL result to show multiple colored strips representing another dimension
108
105
  """
109
106
  df = query_utils.load_query(query_id)
110
- plot = sns.stripplot(df, x=x, y=y, hue=hue, legend=legend)
111
- return _plot_to_image(plot)
107
+ fig = px.strip(df, x=x, y=y, color=color)
108
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
109
+ return _fig_to_image(fig)
112
110
 
113
111
 
114
112
  @mcp.tool()
115
113
  def box_plot(
116
114
  query_id: str,
117
- x: str,
118
- y: str = None,
119
- hue: str = None
115
+ y: str,
116
+ x: str = None,
117
+ color: str = None
120
118
  ):
121
119
  """
122
120
  Make a box plot with the dataframe obtained from running SQL Query against source
123
121
  Args:
124
122
  query_id: Previously run query to use for plotting
125
- x: Column name from SQL result to use for x axis
126
- y: Optional; column name from SQL result to use for y axis
127
- hue: Optional column name from SQL result to use for coloring the points
123
+ y: Column name from SQL result to use for y axis
124
+ x: Optional; Column name from SQL result to use for x axis
125
+ color: Optional column name from SQL result to show multiple colored bars representing another dimension
128
126
  """
129
127
  df = query_utils.load_query(query_id)
130
- plot = sns.boxplot(df, x=x, y=y, hue=hue)
131
- return _plot_to_image(plot)
128
+ fig = px.box(df, x=x, y=y, color=color)
129
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
130
+ return _fig_to_image(fig)
132
131
 
133
132
 
134
133
  @mcp.tool()
@@ -136,8 +135,8 @@ def bar_plot(
136
135
  query_id: str,
137
136
  x: str,
138
137
  y: str = None,
139
- hue: str = None,
140
- orient: str = 'v'
138
+ color: str = None,
139
+ orientation: str = 'v'
141
140
  ):
142
141
  """
143
142
  Make a bar plot with the dataframe obtained from running SQL Query against source
@@ -145,11 +144,12 @@ def bar_plot(
145
144
  query_id: Previously run query to use for plotting
146
145
  x: Column name from SQL result to use for x axis
147
146
  y: Optional; column name from SQL result to use for y axis
148
- hue: Optional column name from SQL result to use for coloring the bars
149
- orient: Orientation of the box plot, use 'v' for vertical and 'h' for horizontal
147
+ color: Optional column name from SQL result to use as a 3rd dimension by splitting each bar into colored sections
148
+ orientation: Orientation of the box plot, use 'v' for vertical (default) and 'h' for horizontal. Be mindful of choosing the correct X and Y columns as per orientation
150
149
  """
151
150
  df = query_utils.load_query(query_id)
152
- plot = sns.barplot(df, x=x, y=y, hue=hue, orient=orient)
153
- return _plot_to_image(plot)
151
+ fig = px.bar(df, x=x, y=y, color=color, orientation=orientation)
152
+ fig.update_xaxes(autotickangles=[0, 45, 60, 90])
153
+ return _fig_to_image(fig)
154
154
 
155
155
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zaturn
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: AI Data Analysis MCP
5
5
  Author-email: Karthik Devan <krtdvn@gmail.com>
6
6
  Maintainer-email: Karthik Devan <krtdvn@gmail.com>
@@ -12,8 +12,10 @@ License-File: LICENSE
12
12
  Requires-Dist: cryptography>=44.0.2
13
13
  Requires-Dist: duckdb>=1.2.1
14
14
  Requires-Dist: fastmcp>=0.4.1
15
+ Requires-Dist: kaleido==0.2.1
15
16
  Requires-Dist: pandas>=2.2.3
16
17
  Requires-Dist: platformdirs>=4.3.7
18
+ Requires-Dist: plotly[express]>=6.0.1
17
19
  Requires-Dist: psycopg2-binary>=2.9.10
18
20
  Requires-Dist: pyarrow>=19.0.1
19
21
  Requires-Dist: pymysql>=1.1.1
@@ -24,21 +26,31 @@ Requires-Dist: sqlalchemy>=2.0.40
24
26
  Requires-Dist: tabulate>=0.9.0
25
27
  Dynamic: license-file
26
28
 
27
- <p align="center">
28
- <img src="https://github.com/kdqed/zaturn/raw/main/brand/logo.png" width="128" height="128">
29
- </p>
29
+ <h1>
30
+ <img src="https://github.com/kdqed/zaturn/raw/main/brand/logo.png" width="24" height="24">
31
+ <span>Zaturn: Your Co-Pilot For Data Analytics & Business Insights</span>
32
+ </h1>
33
+
34
+ Zaturn let's you analyze your data using AI chat; without needing you to write SQL/Python code or fiddling with aesthetically pleasing (but overwhelming) dashboards.
35
+
36
+ You can add Zaturn MCP to Claude Desktop (or any MCP client), connect your data sources, ask questions in natural language, and get instant insights with visualizations. With Zaturn, your AI can automatically understand the kind of data you have, query it, and give you useful pointers with a coherent narrative. You can ask specific questions like "Who is our most valuable customer?", or let AI explore your data with a question like "Here's all the data we have, give us some ideas for the next quarter."
37
+
38
+ [![PyPI Downloads](https://static.pepy.tech/badge/zaturn)](https://pepy.tech/projects/zaturn)
39
+
40
+ [Join The Discord](https://discord.gg/K8mECeVzpQ)
30
41
 
31
- # Zaturn: Your Co-Pilot For Data Analytics & BI
32
42
 
33
43
  <a href="https://glama.ai/mcp/servers/@kdqed/zaturn">
34
44
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@kdqed/zaturn/badge" alt="Zaturn MCP server" />
35
45
  </a>
36
46
 
37
- https://github.com/user-attachments/assets/d42dc433-e5ec-4b3e-bef0-5cfc097396ab
47
+ ## But I can just upload my data to ChatGPT and ask it to analyze right?
38
48
 
39
- Zaturn is an open source, AI-powered data analysis/BI tool that can connect to your data sources, run SQL queries on it, and give you useful insights. Think of it like vibe data analysis, in the spirit of vibe coding. Currently Zaturn is available as an MCP (Model Context Protocol) Server that can be integrated into your favorite MCP Client (Claude, Cursor, etc.) A full fledged notebook interface is on the roadmap.
49
+ Yes, but ChatGPT has an upload size limit of approximately 50MB for CSV files/spreadsheets, and uploading also takes time. Plus, it can't read data straight from your MySQL or PostgreSQL server. Zaturn can overcome all of these limitations, without moving your data anywhere. It simply equips your AI with SQL and visualization capabilities so AI can query your data directly, get the results, process them, and give you instant insights. With Zaturn, AI does not need to process your full dataset and keep it in its memory to answer your questions about the data.
40
50
 
41
- [Join The Discord](https://discord.gg/K8mECeVzpQ)
51
+ ## Zaturn in Action
52
+
53
+ https://github.com/user-attachments/assets/d42dc433-e5ec-4b3e-bef0-5cfc097396ab
42
54
 
43
55
  ## Features:
44
56
 
@@ -64,12 +76,6 @@ In addition to providing tabular and textual summaries, Zaturn can also generate
64
76
  More visualization capabilities are being added.
65
77
 
66
78
 
67
- ## How Does Zaturn Work?
68
-
69
- The naivest way to have an LLM analyze your data is to upload a dataset with a prompt. But that won't get you far, because AI has context window limitations, and it can only go through a few thousand rows at the best. Also, LLM's are not great at doing math.
70
-
71
- Using an MCP like Zaturn will keep your data where it is, and enable AI to draft and run SQL queries on the data. The LLM now processes only the queries and results instead of your entire dataset.
72
-
73
79
  ## Installation & Setup
74
80
  1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/#installation-methods)
75
81
 
@@ -154,11 +160,24 @@ Analyst:
154
160
  ```
155
161
  - A native notebook interface
156
162
 
157
- ## Support And Feedback
163
+ ## Help And Feedback
158
164
 
159
165
  [Raise an issue](https://github.com/kdqed/zaturn/issues) or [join the Discord](https://discord.gg/K8mECeVzpQ).
160
166
 
161
167
 
168
+ ## Support The Project
169
+
170
+ If you find Zaturn useful, please support this project by:
171
+ - Starring the Project
172
+ - Spreading the word
173
+ - [Pledging $9/month on Patreon](https://www.patreon.com/kdqed?utm_medium=github&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink)
174
+
175
+ Your support will enable me to dedicate more of my time to Zaturn.
176
+
162
177
  ## Example Dataset Credits
163
178
 
164
179
  The [pokemon dataset compiled by Sarah Taha and PokéAPI](https://www.kaggle.com/datasets/sarahtaha/1025-pokemon) has been included under the [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) license for demonstration purposes.
180
+
181
+ ## Star History
182
+
183
+ [![Star History Chart](https://api.star-history.com/svg?repos=kdqed/zaturn&type=Date)](https://www.star-history.com/#kdqed/zaturn&Date)
@@ -2,11 +2,11 @@ zaturn/__init__.py,sha256=v4t5fkRuIJFE-SBxCa5pBjZv0EoC0eWK75nU9iaa7Rg,267
2
2
  zaturn/config.py,sha256=gF5M6Agmixw2A4vpWqIF3ICVnClPeASA51dhp1bkk04,3221
3
3
  zaturn/core.py,sha256=9zcKb0FbkgGkDtWfBA6_O5NQf6GVKG69HrqOr5nhsLU,4641
4
4
  zaturn/query_utils.py,sha256=zyQjcRnPKGHZdf0XHzQeMxHw9vieZIwXhBbVGP87ml4,2801
5
- zaturn/visualizations.py,sha256=Dj08msgZ_DIMEVvJIlybT3cIA3GNkcXVOa9TJsHK2yo,4551
5
+ zaturn/visualizations.py,sha256=0ON70D_mK4o0oyfEKqAhr2jkKWz_5-kNKkD6_TGBR9k,5014
6
6
  zaturn/example_data/all_pokemon_data.csv,sha256=SUlGHHWbehuLg-ch1YUrQ6-xBtqHGw6rIkyn70fAgCk,130893
7
- zaturn-0.1.3.dist-info/licenses/LICENSE,sha256=mZSuFlbEBZGl0-8ULRMLdRDbhau5hrWRNQOjytYeaug,1070
8
- zaturn-0.1.3.dist-info/METADATA,sha256=BxES8Ifp0fusfDMeB2SNLpSUrZ2qsKWG8rgqhQnfD0Q,5961
9
- zaturn-0.1.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
10
- zaturn-0.1.3.dist-info/entry_points.txt,sha256=N1UZC2zvod92_Brs4A2xZiAnt-iGLBNryglXfwhxfj4,43
11
- zaturn-0.1.3.dist-info/top_level.txt,sha256=KLUnwQwVZkfd5YCnnqR35MOOs8KLhanPGelvmRo2MVA,7
12
- zaturn-0.1.3.dist-info/RECORD,,
7
+ zaturn-0.1.5.dist-info/licenses/LICENSE,sha256=mZSuFlbEBZGl0-8ULRMLdRDbhau5hrWRNQOjytYeaug,1070
8
+ zaturn-0.1.5.dist-info/METADATA,sha256=Vl68nwLT5NVIdtRRMnV6ncyE4oTIoC3GF_eGJcLN-uA,7077
9
+ zaturn-0.1.5.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
10
+ zaturn-0.1.5.dist-info/entry_points.txt,sha256=N1UZC2zvod92_Brs4A2xZiAnt-iGLBNryglXfwhxfj4,43
11
+ zaturn-0.1.5.dist-info/top_level.txt,sha256=KLUnwQwVZkfd5YCnnqR35MOOs8KLhanPGelvmRo2MVA,7
12
+ zaturn-0.1.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5