zaturn 0.1.3__py3-none-any.whl → 0.1.4__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,4 +1,5 @@
1
1
  from fastmcp import FastMCP, Image
2
+ import math
2
3
  import matplotlib.pyplot as plt
3
4
  import os
4
5
  import seaborn as sns
@@ -7,6 +8,7 @@ from typing import Any, Union, Optional
7
8
  from zaturn import config, query_utils
8
9
 
9
10
  sns.set_theme()
11
+ sns.set_style('ticks')
10
12
 
11
13
  mcp = FastMCP("Zaturn Visualizations")
12
14
 
@@ -14,7 +16,7 @@ mcp = FastMCP("Zaturn Visualizations")
14
16
  def _plot_to_image(plot) -> Union[str, Image]:
15
17
  figure = plot.get_figure()
16
18
  filepath = os.path.join(config.VISUALS_DIR, str(int(time.time())) + '.png')
17
- figure.savefig(filepath)
19
+ figure.savefig(filepath, bbox_inches='tight')
18
20
  plt.clf()
19
21
  if config.RETURN_IMAGES:
20
22
  return Image(path=filepath)
@@ -22,6 +24,47 @@ def _plot_to_image(plot) -> Union[str, Image]:
22
24
  return filepath
23
25
 
24
26
 
27
+ def _fix_x_labels(plot, labels):
28
+ max_label_length = max(list(labels.map(lambda x: len(str(x)))))
29
+
30
+ LABEL_HIDE_FACTOR = 1
31
+ if len(labels) > 20:
32
+ LABEL_HIDE_FACTOR = math.ceil(len(labels)/20)
33
+
34
+ labels_to_show = list(labels)
35
+ ticks = list(plot.get_xticks())
36
+ if LABEL_HIDE_FACTOR > 1:
37
+ ticks = ticks[::LABEL_HIDE_FACTOR]
38
+ labels_to_show = labels_to_show[::LABEL_HIDE_FACTOR]
39
+
40
+ plot.set_xticks(ticks, labels_to_show)
41
+ cutoff = 2 # for rotation
42
+
43
+ if max_label_length >= 12:
44
+ cutoff = 3
45
+ elif max_label_length >= 10:
46
+ cutoff = 4
47
+ elif max_label_length >= 8:
48
+ cutoff = 5
49
+ elif max_label_length >= 7:
50
+ cutoff = 5
51
+ elif max_label_length >= 6:
52
+ cutoff = 6
53
+ elif max_label_length >= 5:
54
+ cutoff = 7
55
+ elif max_label_length >= 4:
56
+ cutoff = 9
57
+ elif max_label_length >= 3:
58
+ cutoff = 13
59
+ else:
60
+ cutoff = 15
61
+
62
+ if len(labels)>cutoff:
63
+ plot.set_xticklabels(plot.get_xticklabels(), rotation=-45, ha='left', va='top')
64
+
65
+ return plot
66
+
67
+
25
68
  # Relationships
26
69
 
27
70
  @mcp.tool()
@@ -42,6 +85,7 @@ def scatter_plot(
42
85
  """
43
86
  df = query_utils.load_query(query_id)
44
87
  plot = sns.scatterplot(df, x=x, y=y, hue=hue)
88
+ plot = _fix_x_labels(plot, df[x])
45
89
  return _plot_to_image(plot)
46
90
 
47
91
 
@@ -62,6 +106,7 @@ def line_plot(
62
106
  """
63
107
  df = query_utils.load_query(query_id)
64
108
  plot = sns.lineplot(df, x=x, y=y, hue=hue)
109
+ plot = _fix_x_labels(plot, df[x])
65
110
  return _plot_to_image(plot)
66
111
 
67
112
 
@@ -108,6 +153,7 @@ def strip_plot(
108
153
  """
109
154
  df = query_utils.load_query(query_id)
110
155
  plot = sns.stripplot(df, x=x, y=y, hue=hue, legend=legend)
156
+ plot = _fix_x_labels(plot, df[x])
111
157
  return _plot_to_image(plot)
112
158
 
113
159
 
@@ -128,6 +174,7 @@ def box_plot(
128
174
  """
129
175
  df = query_utils.load_query(query_id)
130
176
  plot = sns.boxplot(df, x=x, y=y, hue=hue)
177
+ plot = _fix_x_labels(plot, df[x])
131
178
  return _plot_to_image(plot)
132
179
 
133
180
 
@@ -150,6 +197,7 @@ def bar_plot(
150
197
  """
151
198
  df = query_utils.load_query(query_id)
152
199
  plot = sns.barplot(df, x=x, y=y, hue=hue, orient=orient)
200
+ plot = _fix_x_labels(plot, df[x])
153
201
  return _plot_to_image(plot)
154
202
 
155
203
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zaturn
3
- Version: 0.1.3
3
+ Version: 0.1.4
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>
@@ -24,21 +24,31 @@ Requires-Dist: sqlalchemy>=2.0.40
24
24
  Requires-Dist: tabulate>=0.9.0
25
25
  Dynamic: license-file
26
26
 
27
- <p align="center">
28
- <img src="https://github.com/kdqed/zaturn/raw/main/brand/logo.png" width="128" height="128">
29
- </p>
27
+ <h1>
28
+ <img src="https://github.com/kdqed/zaturn/raw/main/brand/logo.png" width="24" height="24">
29
+ <span>Zaturn: Your Co-Pilot For Data Analytics & Business Insights</span>
30
+ </h1>
31
+
32
+ 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.
33
+
34
+ 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."
35
+
36
+ [![PyPI Downloads](https://static.pepy.tech/badge/zaturn)](https://pepy.tech/projects/zaturn)
37
+
38
+ [Join The Discord](https://discord.gg/K8mECeVzpQ)
30
39
 
31
- # Zaturn: Your Co-Pilot For Data Analytics & BI
32
40
 
33
41
  <a href="https://glama.ai/mcp/servers/@kdqed/zaturn">
34
42
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@kdqed/zaturn/badge" alt="Zaturn MCP server" />
35
43
  </a>
36
44
 
37
- https://github.com/user-attachments/assets/d42dc433-e5ec-4b3e-bef0-5cfc097396ab
45
+ ## But I can just upload my data to ChatGPT and ask it to analyze right?
38
46
 
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.
47
+ 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
48
 
41
- [Join The Discord](https://discord.gg/K8mECeVzpQ)
49
+ ## Zaturn in Action
50
+
51
+ https://github.com/user-attachments/assets/d42dc433-e5ec-4b3e-bef0-5cfc097396ab
42
52
 
43
53
  ## Features:
44
54
 
@@ -64,12 +74,6 @@ In addition to providing tabular and textual summaries, Zaturn can also generate
64
74
  More visualization capabilities are being added.
65
75
 
66
76
 
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
77
  ## Installation & Setup
74
78
  1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/#installation-methods)
75
79
 
@@ -162,3 +166,7 @@ Analyst:
162
166
  ## Example Dataset Credits
163
167
 
164
168
  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.
169
+
170
+ ## Star History
171
+
172
+ [![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=4RA4FytYNPiBdMyIqlw3dfjH7flT2Nz6ncVoVoIqPEA,5883
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.4.dist-info/licenses/LICENSE,sha256=mZSuFlbEBZGl0-8ULRMLdRDbhau5hrWRNQOjytYeaug,1070
8
+ zaturn-0.1.4.dist-info/METADATA,sha256=VPtw2YcLYUz54oLKX72sCjzImF7xiqrM65e2u1j2-EE,6658
9
+ zaturn-0.1.4.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
10
+ zaturn-0.1.4.dist-info/entry_points.txt,sha256=N1UZC2zvod92_Brs4A2xZiAnt-iGLBNryglXfwhxfj4,43
11
+ zaturn-0.1.4.dist-info/top_level.txt,sha256=KLUnwQwVZkfd5YCnnqR35MOOs8KLhanPGelvmRo2MVA,7
12
+ zaturn-0.1.4.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