jdesiree commited on
Commit
0a6f3b4
·
verified ·
1 Parent(s): 07748f3

Update graph_tool.py

Browse files
Files changed (1) hide show
  1. graph_tool.py +50 -30
graph_tool.py CHANGED
@@ -4,12 +4,13 @@ import matplotlib.pyplot as plt
4
  import numpy as np
5
  import json
6
 
7
- def generate_plot(plot_config_json):
8
  """
9
- Generates a plot (bar, line, or pie) and returns it as an HTML-formatted Base64-encoded image string.
 
10
 
11
  Args:
12
- plot_config_json (str): JSON string containing all plot configuration:
13
  {
14
  "data": {"key1": value1, "key2": value2, ...},
15
  "labels": ["label1", "label2", ...],
@@ -18,13 +19,14 @@ def generate_plot(plot_config_json):
18
  "x_label": "X Axis Label" (optional),
19
  "y_label": "Y Axis Label" (optional)
20
  }
 
21
 
22
  Returns:
23
- str: An HTML img tag with Base64-encoded plot image.
24
  """
25
  try:
26
  # Parse the main JSON configuration
27
- config = json.loads(plot_config_json)
28
  except json.JSONDecodeError as e:
29
  return f'<p style="color:red;">Error parsing JSON configuration: {e}</p>'
30
 
@@ -43,6 +45,9 @@ def generate_plot(plot_config_json):
43
  if not isinstance(data, dict):
44
  return '<p style="color:red;">Data must be a dictionary with keys as labels and values as numbers.</p>'
45
 
 
 
 
46
  if not isinstance(labels, list):
47
  return '<p style="color:red;">Labels must be a list.</p>'
48
 
@@ -59,10 +64,15 @@ def generate_plot(plot_config_json):
59
  except (ValueError, TypeError):
60
  return '<p style="color:red;">All data values must be numeric.</p>'
61
 
 
 
 
 
62
  if plot_type == 'bar':
63
  bars = ax.bar(x_data, y_data)
64
  ax.set_xlabel(x_label)
65
  ax.set_ylabel(y_label)
 
66
 
67
  # Add value labels on top of bars
68
  for bar, value in zip(bars, y_data):
@@ -74,15 +84,21 @@ def generate_plot(plot_config_json):
74
  ax.plot(x_data, y_data, marker='o', linewidth=2, markersize=6)
75
  ax.set_xlabel(x_label)
76
  ax.set_ylabel(y_label)
 
77
  ax.grid(True, alpha=0.3)
78
 
79
  elif plot_type == 'pie':
80
  # For pie charts, use labels parameter if provided, otherwise use data keys
81
- pie_labels = labels if len(labels) == len(y_data) else x_data
82
- wedges, texts, autotexts = ax.pie(y_data, labels=pie_labels, autopct='%1.1f%%',
83
- startangle=90, textprops={'fontsize': 10})
 
 
 
 
 
84
  ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle
85
- # Don't set x/y labels for pie charts as they don't make sense
86
 
87
  else:
88
  return f'<p style="color:red;">Invalid plot_type: {plot_type}. Choose "bar", "line", or "pie".</p>'
@@ -94,33 +110,37 @@ def generate_plot(plot_config_json):
94
 
95
  # Save plot to a BytesIO buffer in memory
96
  buf = BytesIO()
97
- plt.savefig(buf, format='png', bbox_inches='tight', dpi=150,
98
- facecolor='white', edgecolor='none')
 
 
 
 
 
 
99
  plt.close(fig) # Close the plot to free up memory
100
 
101
  # Encode the image data to a Base64 string
102
  img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8')
103
 
104
- # Return HTML img tag with proper styling
105
- return f'''
106
- <div style="text-align: center; margin: 20px 0;">
107
- <img src="data:image/png;base64,{img_base64}"
108
- style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"
109
- alt="{title}" />
110
- </div>
111
- '''
 
 
 
 
 
 
 
 
 
112
 
113
  except Exception as e:
114
  plt.close('all') # Clean up any open figures
115
  return f'<p style="color:red;">Error generating plot: {str(e)}</p>'
116
-
117
- # Example usage:
118
- # plot_config = {
119
- # "data": {"A": 10, "B": 20, "C": 15},
120
- # "labels": ["Category A", "Category B", "Category C"],
121
- # "plot_type": "bar",
122
- # "title": "Sample Bar Chart",
123
- # "x_label": "Categories",
124
- # "y_label": "Values"
125
- # }
126
- # result = generate_plot_single_input(json.dumps(plot_config))
 
4
  import numpy as np
5
  import json
6
 
7
+ def generate_plot(input: str, return_html: bool = True):
8
  """
9
+ Generates a plot (bar, line, or pie) and returns it as an HTML-formatted Base64-encoded image string,
10
+ or just the Base64 string if return_html=False.
11
 
12
  Args:
13
+ input (str): JSON string containing all plot configuration:
14
  {
15
  "data": {"key1": value1, "key2": value2, ...},
16
  "labels": ["label1", "label2", ...],
 
19
  "x_label": "X Axis Label" (optional),
20
  "y_label": "Y Axis Label" (optional)
21
  }
22
+ return_html (bool): Whether to return full HTML <img> tag (default True).
23
 
24
  Returns:
25
+ str: Either an HTML <img> tag or a raw Base64-encoded image string.
26
  """
27
  try:
28
  # Parse the main JSON configuration
29
+ config = json.loads(input)
30
  except json.JSONDecodeError as e:
31
  return f'<p style="color:red;">Error parsing JSON configuration: {e}</p>'
32
 
 
45
  if not isinstance(data, dict):
46
  return '<p style="color:red;">Data must be a dictionary with keys as labels and values as numbers.</p>'
47
 
48
+ if not data:
49
+ return '<p style="color:red;">Data dictionary is empty.</p>'
50
+
51
  if not isinstance(labels, list):
52
  return '<p style="color:red;">Labels must be a list.</p>'
53
 
 
64
  except (ValueError, TypeError):
65
  return '<p style="color:red;">All data values must be numeric.</p>'
66
 
67
+ # Replace x-axis labels if provided and length matches
68
+ if labels and len(labels) == len(x_data):
69
+ x_data = labels
70
+
71
  if plot_type == 'bar':
72
  bars = ax.bar(x_data, y_data)
73
  ax.set_xlabel(x_label)
74
  ax.set_ylabel(y_label)
75
+ ax.set_ylim(bottom=0)
76
 
77
  # Add value labels on top of bars
78
  for bar, value in zip(bars, y_data):
 
84
  ax.plot(x_data, y_data, marker='o', linewidth=2, markersize=6)
85
  ax.set_xlabel(x_label)
86
  ax.set_ylabel(y_label)
87
+ ax.set_ylim(bottom=0)
88
  ax.grid(True, alpha=0.3)
89
 
90
  elif plot_type == 'pie':
91
  # For pie charts, use labels parameter if provided, otherwise use data keys
92
+ pie_labels = labels if len(labels) == len(y_data) else list(data.keys())
93
+ wedges, texts, autotexts = ax.pie(
94
+ y_data,
95
+ labels=pie_labels,
96
+ autopct='%1.1f%%',
97
+ startangle=90,
98
+ textprops={'fontsize': 10}
99
+ )
100
  ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle
101
+ # Don't set x/y labels for pie charts
102
 
103
  else:
104
  return f'<p style="color:red;">Invalid plot_type: {plot_type}. Choose "bar", "line", or "pie".</p>'
 
110
 
111
  # Save plot to a BytesIO buffer in memory
112
  buf = BytesIO()
113
+ plt.savefig(
114
+ buf,
115
+ format='png',
116
+ bbox_inches='tight',
117
+ dpi=150,
118
+ facecolor='white',
119
+ edgecolor='none'
120
+ )
121
  plt.close(fig) # Close the plot to free up memory
122
 
123
  # Encode the image data to a Base64 string
124
  img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8')
125
 
126
+ if return_html:
127
+ # More descriptive alt text for accessibility
128
+ alt_text = title
129
+ if plot_type == "pie":
130
+ alt_text += " - " + ", ".join(f"{lbl}: {val}" for lbl, val in zip(pie_labels, y_data))
131
+ else:
132
+ alt_text += " - " + ", ".join(f"{lbl}: {val}" for lbl, val in zip(x_data, y_data))
133
+
134
+ return f'''
135
+ <div style="text-align: center; margin: 20px 0;">
136
+ <img src="data:image/png;base64,{img_base64}"
137
+ style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"
138
+ alt="{alt_text}" />
139
+ </div>
140
+ '''
141
+ else:
142
+ return img_base64
143
 
144
  except Exception as e:
145
  plt.close('all') # Clean up any open figures
146
  return f'<p style="color:red;">Error generating plot: {str(e)}</p>'