class IllustrationGenerator
A class that generates educational illustrations and technical drawings for mathematical and scientific concepts using matplotlib and programmatic rendering.
/tf/active/vicechatdev/e-ink-llm/graphics_generator.py
375 - 527
moderate
Purpose
The IllustrationGenerator class is responsible for creating visual educational content including mathematical function plots, scientific diagrams (like atomic structures), and generic illustrations. It provides a unified interface for generating different types of educational graphics based on specifications, with fallback error handling. The class uses matplotlib for rendering and returns base64-encoded PNG images suitable for embedding in documents or web pages.
Source Code
class IllustrationGenerator:
"""Generates educational illustrations and technical drawings"""
def __init__(self, api_key: str):
self.client = OpenAI(api_key=api_key)
async def generate_illustration(self, spec: GraphicSpec) -> GraphicSpec:
"""Generate an illustration using AI or programmatic methods"""
params = spec.parameters
concept = params.get('concept', spec.description)
style = params.get('style', 'educational')
try:
# For educational concepts, try programmatic generation first
if 'mathematical' in style or 'math' in concept:
return self._create_math_illustration(spec)
elif 'scientific' in style or 'science' in concept:
return self._create_science_illustration(spec)
else:
# For complex illustrations, could use DALL-E (if needed)
return self._create_generic_illustration(spec)
except Exception as e:
print(f"Error generating illustration: {e}")
return self._create_error_illustration(spec, f"Illustration generation failed: {e}")
def _create_math_illustration(self, spec: GraphicSpec) -> GraphicSpec:
"""Create mathematical concept illustrations"""
params = spec.parameters
concept = params.get('concept', 'function').lower()
fig, ax = plt.subplots(figsize=(8, 6))
if 'function' in concept or 'quadratic' in concept:
# Draw a quadratic function
x = np.linspace(-5, 5, 100)
y = x**2
ax.plot(x, y, 'black', linewidth=2)
ax.axhline(y=0, color='black', linewidth=0.5)
ax.axvline(x=0, color='black', linewidth=0.5)
ax.grid(True, alpha=0.3)
ax.set_title('Quadratic Function: y = x²', fontsize=14, fontweight='bold')
elif 'derivative' in concept:
# Show function and its derivative
x = np.linspace(-3, 3, 100)
y = x**2
dy = 2*x
ax.plot(x, y, 'black', linewidth=2, label='f(x) = x²')
ax.plot(x, dy, 'gray', linewidth=2, linestyle='--', label="f'(x) = 2x")
ax.legend()
ax.grid(True, alpha=0.3)
ax.set_title('Function and its Derivative', fontsize=14, fontweight='bold')
else:
# Generic mathematical illustration
ax.text(0.5, 0.5, f'Mathematical Concept:\n{concept}',
ha='center', va='center', transform=ax.transAxes,
fontsize=14, bbox=dict(boxstyle="round,pad=0.3", facecolor="lightgray"))
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.tight_layout()
spec.image_data = self._fig_to_base64(fig)
spec.width = 800
spec.height = 600
plt.close(fig)
return spec
def _create_science_illustration(self, spec: GraphicSpec) -> GraphicSpec:
"""Create scientific concept illustrations"""
params = spec.parameters
concept = params.get('concept', 'atoms').lower()
fig, ax = plt.subplots(figsize=(8, 6))
if 'atom' in concept:
# Draw simple atomic structure
center = Circle((0.5, 0.5), 0.1, facecolor='gray', edgecolor='black')
ax.add_patch(center)
# Electron orbits
for radius in [0.2, 0.3, 0.4]:
orbit = Circle((0.5, 0.5), radius, fill=False, edgecolor='black', linestyle='--')
ax.add_patch(orbit)
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_title('Atomic Structure', fontsize=14, fontweight='bold')
else:
# Generic scientific illustration
ax.text(0.5, 0.5, f'Scientific Concept:\n{concept}',
ha='center', va='center', transform=ax.transAxes,
fontsize=14, bbox=dict(boxstyle="round,pad=0.3", facecolor="lightgray"))
ax.axis('off')
plt.tight_layout()
spec.image_data = self._fig_to_base64(fig)
spec.width = 800
spec.height = 600
plt.close(fig)
return spec
def _create_generic_illustration(self, spec: GraphicSpec) -> GraphicSpec:
"""Create a generic illustration placeholder"""
fig, ax = plt.subplots(figsize=(8, 6))
ax.text(0.5, 0.5, f'Illustration:\n{spec.description}',
ha='center', va='center', transform=ax.transAxes,
fontsize=14, bbox=dict(boxstyle="round,pad=0.3", facecolor="lightgray"))
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.axis('off')
ax.set_title(spec.description, fontsize=14, fontweight='bold')
plt.tight_layout()
spec.image_data = self._fig_to_base64(fig)
spec.width = 800
spec.height = 600
plt.close(fig)
return spec
def _fig_to_base64(self, fig) -> str:
"""Convert matplotlib figure to base64 encoded image"""
buffer = io.BytesIO()
fig.savefig(buffer, format='png', dpi=150, bbox_inches='tight',
facecolor='white', edgecolor='none')
buffer.seek(0)
image_data = buffer.getvalue()
buffer.close()
return base64.b64encode(image_data).decode('utf-8')
def _create_error_illustration(self, spec: GraphicSpec, error_msg: str) -> GraphicSpec:
"""Create an error placeholder illustration"""
fig, ax = plt.subplots(figsize=(6, 4))
ax.text(0.5, 0.5, f"Error: {error_msg}", ha='center', va='center',
transform=ax.transAxes, fontsize=12,
bbox=dict(boxstyle="round,pad=0.3", facecolor="lightgray"))
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.axis('off')
spec.image_data = self._fig_to_base64(fig)
spec.width = 600
spec.height = 400
plt.close(fig)
return spec
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
api_key: OpenAI API key string used to initialize the OpenAI client. Required for instantiation even though current implementation primarily uses programmatic generation rather than AI-based image generation. This suggests the class may be designed to support DALL-E integration for complex illustrations in the future.
Return Value
Instantiation returns an IllustrationGenerator object. The main method generate_illustration() returns a GraphicSpec object with populated image_data (base64-encoded PNG), width, and height attributes. All internal methods also return modified GraphicSpec objects with generated illustration data.
Class Interface
Methods
__init__(self, api_key: str)
Purpose: Initialize the IllustrationGenerator with an OpenAI API key
Parameters:
api_key: OpenAI API key string for client initialization
Returns: None (constructor)
async generate_illustration(self, spec: GraphicSpec) -> GraphicSpec
Purpose: Main entry point to generate an illustration based on the provided specification, routing to appropriate generation method based on style and concept
Parameters:
spec: GraphicSpec object containing description and parameters dictionary with 'concept' and 'style' keys
Returns: Modified GraphicSpec object with populated image_data (base64 PNG), width, and height attributes
_create_math_illustration(self, spec: GraphicSpec) -> GraphicSpec
Purpose: Create mathematical concept illustrations including quadratic functions, derivatives, and generic math concepts
Parameters:
spec: GraphicSpec object with parameters containing 'concept' key (e.g., 'function', 'quadratic', 'derivative')
Returns: GraphicSpec object with generated mathematical illustration as base64-encoded PNG
_create_science_illustration(self, spec: GraphicSpec) -> GraphicSpec
Purpose: Create scientific concept illustrations including atomic structures and generic science concepts
Parameters:
spec: GraphicSpec object with parameters containing 'concept' key (e.g., 'atom', 'atoms')
Returns: GraphicSpec object with generated scientific illustration as base64-encoded PNG
_create_generic_illustration(self, spec: GraphicSpec) -> GraphicSpec
Purpose: Create a generic placeholder illustration with the description text displayed
Parameters:
spec: GraphicSpec object with description to be displayed in the illustration
Returns: GraphicSpec object with generic placeholder illustration as base64-encoded PNG
_fig_to_base64(self, fig) -> str
Purpose: Convert a matplotlib figure object to a base64-encoded PNG string
Parameters:
fig: matplotlib.figure.Figure object to be converted
Returns: Base64-encoded string representation of the figure as PNG image
_create_error_illustration(self, spec: GraphicSpec, error_msg: str) -> GraphicSpec
Purpose: Create an error placeholder illustration displaying the error message
Parameters:
spec: GraphicSpec object to be populated with error illustrationerror_msg: Error message string to display in the illustration
Returns: GraphicSpec object with error placeholder illustration as base64-encoded PNG
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
client |
OpenAI | OpenAI client instance initialized with the provided API key, potentially for future DALL-E integration | instance |
Dependencies
openaimatplotlibnumpyiobase64
Required Imports
from openai import OpenAI
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import numpy as np
import io
import base64
Conditional/Optional Imports
These imports are only needed under specific conditions:
from matplotlib.patches import Circle
Condition: only needed when generating scientific illustrations with atomic structures
Required (conditional)Usage Example
from openai import OpenAI
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import numpy as np
import io
import base64
from dataclasses import dataclass
from typing import Dict, Any, Optional
@dataclass
class GraphicSpec:
description: str
parameters: Dict[str, Any]
image_data: Optional[str] = None
width: int = 0
height: int = 0
# Instantiate the generator
generator = IllustrationGenerator(api_key='your-openai-api-key')
# Create a math illustration
math_spec = GraphicSpec(
description='Quadratic function',
parameters={'concept': 'quadratic function', 'style': 'mathematical'}
)
result = await generator.generate_illustration(math_spec)
print(f'Generated image size: {result.width}x{result.height}')
# Create a science illustration
science_spec = GraphicSpec(
description='Atomic structure',
parameters={'concept': 'atom model', 'style': 'scientific'}
)
result = await generator.generate_illustration(science_spec)
# Create a generic illustration
generic_spec = GraphicSpec(
description='Custom concept',
parameters={'concept': 'custom educational concept'}
)
result = await generator.generate_illustration(generic_spec)
Best Practices
- Always await the generate_illustration() method as it is async
- Ensure GraphicSpec objects have properly formatted parameters dictionary with 'concept' and 'style' keys
- The class automatically closes matplotlib figures to prevent memory leaks
- Use 'mathematical' or 'math' in style/concept for math illustrations, 'scientific' or 'science' for science illustrations
- The returned GraphicSpec object contains base64-encoded PNG data in the image_data attribute
- Error handling is built-in; failed generations return error placeholder illustrations rather than raising exceptions
- The OpenAI client is initialized but not currently used in the implementation; this may be for future DALL-E integration
- All generated images are 800x600 pixels by default (600x400 for error illustrations)
- Images are rendered at 150 DPI with white background and tight bounding boxes
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class GraphicsGenerator 73.0% similar
-
class DiagramGenerator 69.8% similar
-
class ChartGenerator 67.1% similar
-
function demo_graphics_generation 61.8% similar
-
class SignatureGenerator 59.4% similar