jdesiree commited on
Commit
b2f206d
·
verified ·
1 Parent(s): 31a90a8

Update graph_tool.py

Browse files
Files changed (1) hide show
  1. graph_tool.py +86 -32
graph_tool.py CHANGED
@@ -2,47 +2,101 @@ import base64
2
  from io import BytesIO
3
  import matplotlib.pyplot as plt
4
  import numpy as np
 
5
 
6
- def generate_plot(data, labels, plot_type, title, x_label="", y_label=""):
7
  """
8
- Generates a plot (bar, line, or pie) and returns it as a Base64-encoded string.
9
 
10
  Args:
11
- data (dict): A dictionary where keys are labels and values are numerical data.
12
- labels (list): The labels for the data points.
13
  plot_type (str): The type of plot to generate ('bar', 'line', or 'pie').
14
  title (str): The title of the plot.
15
  x_label (str): The label for the x-axis.
16
  y_label (str): The label for the y-axis.
17
 
18
  Returns:
19
- str: A Base64-encoded string of the plot image.
20
  """
21
- fig, ax = plt.subplots()
22
-
23
- # Extract keys and values from the data dictionary
24
- x_data = list(data.keys())
25
- y_data = list(data.values())
26
-
27
- if plot_type == 'bar':
28
- ax.bar(x_data, y_data, tick_label=labels)
29
- elif plot_type == 'line':
30
- ax.plot(x_data, y_data)
31
- elif plot_type == 'pie':
32
- ax.pie(y_data, labels=x_data, autopct='%1.1f%%', startangle=90)
33
- ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
34
- else:
35
- raise ValueError("Invalid plot_type. Choose 'bar', 'line', or 'pie'.")
36
-
37
- ax.set_title(title)
38
- ax.set_xlabel(x_label)
39
- ax.set_ylabel(y_label)
40
-
41
- # Save plot to a BytesIO buffer in memory instead of to a file
42
- buf = BytesIO()
43
- plt.savefig(buf, format='png', bbox_inches='tight')
44
- plt.close(fig) # Close the plot to free up memory
45
 
46
- # Encode the image data to a Base64 string
47
- img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8')
48
- return f'<img src="data:image/png;base64,{img_base64}"/>'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from io import BytesIO
3
  import matplotlib.pyplot as plt
4
  import numpy as np
5
+ import json
6
 
7
+ def generate_plot(data_json, labels_json, plot_type, title, x_label="", y_label=""):
8
  """
9
+ Generates a plot (bar, line, or pie) and returns it as an HTML-formatted Base64-encoded image string.
10
 
11
  Args:
12
+ data_json (str): JSON string containing data dictionary where keys are labels and values are numerical data.
13
+ labels_json (str): JSON string containing list of labels for the data points.
14
  plot_type (str): The type of plot to generate ('bar', 'line', or 'pie').
15
  title (str): The title of the plot.
16
  x_label (str): The label for the x-axis.
17
  y_label (str): The label for the y-axis.
18
 
19
  Returns:
20
+ str: An HTML img tag with Base64-encoded plot image.
21
  """
22
+ try:
23
+ # Parse JSON strings
24
+ data = json.loads(data_json)
25
+ labels = json.loads(labels_json)
26
+ except json.JSONDecodeError as e:
27
+ return f'<p style="color:red;">Error parsing JSON data: {e}</p>'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # Validate inputs
30
+ if not isinstance(data, dict):
31
+ return '<p style="color:red;">Data must be a dictionary with keys as labels and values as numbers.</p>'
32
+
33
+ if not isinstance(labels, list):
34
+ return '<p style="color:red;">Labels must be a list.</p>'
35
+
36
+ try:
37
+ fig, ax = plt.subplots(figsize=(10, 6))
38
+
39
+ # Extract keys and values from the data dictionary
40
+ x_data = list(data.keys())
41
+ y_data = list(data.values())
42
+
43
+ # Ensure y_data contains numeric values
44
+ try:
45
+ y_data = [float(val) for val in y_data]
46
+ except (ValueError, TypeError):
47
+ return '<p style="color:red;">All data values must be numeric.</p>'
48
+
49
+ if plot_type == 'bar':
50
+ bars = ax.bar(x_data, y_data)
51
+ ax.set_xlabel(x_label)
52
+ ax.set_ylabel(y_label)
53
+
54
+ # Add value labels on top of bars
55
+ for bar, value in zip(bars, y_data):
56
+ height = bar.get_height()
57
+ ax.text(bar.get_x() + bar.get_width()/2., height,
58
+ f'{value}', ha='center', va='bottom')
59
+
60
+ elif plot_type == 'line':
61
+ ax.plot(x_data, y_data, marker='o', linewidth=2, markersize=6)
62
+ ax.set_xlabel(x_label)
63
+ ax.set_ylabel(y_label)
64
+ ax.grid(True, alpha=0.3)
65
+
66
+ elif plot_type == 'pie':
67
+ # For pie charts, use labels parameter if provided, otherwise use data keys
68
+ pie_labels = labels if len(labels) == len(y_data) else x_data
69
+ wedges, texts, autotexts = ax.pie(y_data, labels=pie_labels, autopct='%1.1f%%',
70
+ startangle=90, textprops={'fontsize': 10})
71
+ ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle
72
+ # Don't set x/y labels for pie charts as they don't make sense
73
+
74
+ else:
75
+ return f'<p style="color:red;">Invalid plot_type: {plot_type}. Choose "bar", "line", or "pie".</p>'
76
+
77
+ ax.set_title(title, fontsize=14, fontweight='bold', pad=20)
78
+
79
+ # Improve layout
80
+ plt.tight_layout()
81
+
82
+ # Save plot to a BytesIO buffer in memory
83
+ buf = BytesIO()
84
+ plt.savefig(buf, format='png', bbox_inches='tight', dpi=150,
85
+ facecolor='white', edgecolor='none')
86
+ plt.close(fig) # Close the plot to free up memory
87
+
88
+ # Encode the image data to a Base64 string
89
+ img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8')
90
+
91
+ # Return HTML img tag with proper styling
92
+ return f'''
93
+ <div style="text-align: center; margin: 20px 0;">
94
+ <img src="data:image/png;base64,{img_base64}"
95
+ style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"
96
+ alt="{title}" />
97
+ </div>
98
+ '''
99
+
100
+ except Exception as e:
101
+ plt.close('all') # Clean up any open figures
102
+ return f'<p style="color:red;">Error generating plot: {str(e)}</p>'