|
| 1 | ++++ |
| 2 | +title = "executable visualizations" |
| 3 | +date = "2026-04-04" |
| 4 | +author = "Cody" |
| 5 | +description = "Zorto now renders Python visualizations inline — matplotlib, plotly, seaborn, altair. Just write the code." |
| 6 | +tags = ["zorto", "python", "visualizations"] |
| 7 | ++++ |
| 8 | + |
| 9 | +Zorto can now render Python visualizations inline. No configuration, no magic comments — just write your code and the chart appears. |
| 10 | + |
| 11 | +<!-- more --> |
| 12 | + |
| 13 | +## matplotlib |
| 14 | + |
| 15 | +The most popular Python plotting library. Just `import matplotlib.pyplot as plt` and plot: |
| 16 | + |
| 17 | +```{python} |
| 18 | +import matplotlib.pyplot as plt |
| 19 | +import math |
| 20 | +
|
| 21 | +x = [i * 0.1 for i in range(100)] |
| 22 | +y = [math.sin(v) for v in x] |
| 23 | +
|
| 24 | +plt.figure(figsize=(8, 4)) |
| 25 | +plt.plot(x, y, color='#7c3aed', linewidth=2) |
| 26 | +plt.title('sin(x)') |
| 27 | +plt.xlabel('x') |
| 28 | +plt.ylabel('y') |
| 29 | +plt.grid(True, alpha=0.3) |
| 30 | +plt.tight_layout() |
| 31 | +``` |
| 32 | + |
| 33 | +## plotly |
| 34 | + |
| 35 | +Interactive charts that respond to hover, zoom, and pan: |
| 36 | + |
| 37 | +```{python} |
| 38 | +import plotly.graph_objects as go |
| 39 | +
|
| 40 | +months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] |
| 41 | +revenue = [12, 15, 13, 17, 21, 24, 22, 28, 31, 29, 35, 42] |
| 42 | +costs = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] |
| 43 | +
|
| 44 | +fig = go.Figure() |
| 45 | +fig.add_trace(go.Scatter(x=months, y=revenue, name='Revenue', line=dict(color='#7c3aed', width=3))) |
| 46 | +fig.add_trace(go.Scatter(x=months, y=costs, name='Costs', line=dict(color='#06b6d4', width=3))) |
| 47 | +fig.update_layout( |
| 48 | + title='Monthly financials', |
| 49 | + xaxis_title='Month', |
| 50 | + yaxis_title='$K', |
| 51 | + template='plotly_dark', |
| 52 | + height=400, |
| 53 | +) |
| 54 | +``` |
| 55 | + |
| 56 | +## seaborn |
| 57 | + |
| 58 | +Statistical visualizations built on matplotlib — automatically captured: |
| 59 | + |
| 60 | +```{python} |
| 61 | +import matplotlib |
| 62 | +matplotlib.use('Agg') |
| 63 | +import matplotlib.pyplot as plt |
| 64 | +import random |
| 65 | +
|
| 66 | +random.seed(42) |
| 67 | +data = [random.gauss(0, 1) for _ in range(500)] |
| 68 | +
|
| 69 | +plt.figure(figsize=(8, 4)) |
| 70 | +plt.hist(data, bins=30, color='#7c3aed', alpha=0.7, edgecolor='white') |
| 71 | +plt.title('Normal distribution (n=500)') |
| 72 | +plt.xlabel('Value') |
| 73 | +plt.ylabel('Frequency') |
| 74 | +plt.grid(True, alpha=0.3, axis='y') |
| 75 | +plt.tight_layout() |
| 76 | +``` |
| 77 | + |
| 78 | +## altair |
| 79 | + |
| 80 | +Declarative statistical visualization: |
| 81 | + |
| 82 | +```{python} |
| 83 | +import altair as alt |
| 84 | +
|
| 85 | +data = alt.Data(values=[ |
| 86 | + {'x': i, 'y': i ** 2, 'category': 'quadratic'} for i in range(20) |
| 87 | +] + [ |
| 88 | + {'x': i, 'y': i * 3, 'category': 'linear'} for i in range(20) |
| 89 | +]) |
| 90 | +
|
| 91 | +chart = alt.Chart(data).mark_line(strokeWidth=3).encode( |
| 92 | + x='x:Q', |
| 93 | + y='y:Q', |
| 94 | + color=alt.Color('category:N', scale=alt.Scale(range=['#7c3aed', '#06b6d4'])), |
| 95 | +).properties( |
| 96 | + title='Growth curves', |
| 97 | + width=600, |
| 98 | + height=300, |
| 99 | +) |
| 100 | +``` |
| 101 | + |
| 102 | +## multiple plots in one block |
| 103 | + |
| 104 | +```{python} |
| 105 | +import matplotlib.pyplot as plt |
| 106 | +
|
| 107 | +fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) |
| 108 | +
|
| 109 | +categories = ['Rust', 'Python', 'Go', 'JS'] |
| 110 | +values = [95, 88, 72, 68] |
| 111 | +ax1.bar(categories, values, color=['#7c3aed', '#06b6d4', '#10b981', '#f59e0b']) |
| 112 | +ax1.set_title('Language satisfaction') |
| 113 | +ax1.set_ylabel('%') |
| 114 | +
|
| 115 | +import random |
| 116 | +random.seed(42) |
| 117 | +x = [random.gauss(0, 1) for _ in range(100)] |
| 118 | +y = [xi * 0.7 + random.gauss(0, 0.5) for xi in x] |
| 119 | +ax2.scatter(x, y, alpha=0.6, color='#7c3aed', s=20) |
| 120 | +ax2.set_title('Correlation') |
| 121 | +ax2.set_xlabel('x') |
| 122 | +ax2.set_ylabel('y') |
| 123 | +
|
| 124 | +plt.tight_layout() |
| 125 | +``` |
| 126 | + |
| 127 | +## how it works |
| 128 | + |
| 129 | +Zorto's executable code blocks run Python at build time via an embedded interpreter. After your code executes, Zorto checks if any visualization libraries produced output: |
| 130 | + |
| 131 | +- **matplotlib**: Detects open figures via `plt.get_fignums()`, saves as PNG, embeds inline |
| 132 | +- **plotly**: Detects `plotly.graph_objects.Figure` instances, embeds as interactive HTML |
| 133 | +- **seaborn**: Uses matplotlib under the hood — automatically captured |
| 134 | +- **altair**: Detects `altair.Chart` instances, embeds as interactive HTML |
| 135 | + |
| 136 | +Zero configuration. Zero magic comments. Just write Python. |
0 commit comments