Agent skill
g2_charts
Install this agent skill to your Project
npx add-skill https://github.com/drshailesh88/integrated_content_OS/tree/main/skills/cardiology/visual-design-system/g2_charts
SKILL.md
G2 Grammar-Based Charts
Purpose: Declarative, grammar-based charting using AntV G2 for complex medical visualizations.
Status: ✅ Production Ready
Repository: https://github.com/antvis/G2 (12.5k ⭐)
Quick Start
from g2_charts.medical_grammars import forest_plot_grammar
from g2_charts.grammar_renderer import G2Chart
# Create grammar specification
grammar = forest_plot_grammar(
studies=['DAPA-HF', 'EMPEROR-Reduced'],
estimates=[0.74, 0.75],
lower_ci=[0.65, 0.65],
upper_ci=[0.85, 0.86],
title="SGLT2i Trials"
)
# Render chart
chart = G2Chart(width=800, height=600)
chart.grammar = grammar
chart.render('forest.png')
What is Grammar-Based Charting?
Instead of imperative "draw this, then this", you declare what the data means:
# Imperative (Plotly style)
fig = go.Figure()
fig.add_trace(go.Scatter(x=..., y=...))
fig.add_trace(go.Bar(x=..., y=...))
fig.update_layout(...)
# Declarative (G2 grammar)
grammar = {
'data': [...],
'marks': [
{'type': 'point', 'encode': {'x': 'time', 'y': 'survival'}},
{'type': 'line', 'encode': {'x': 'time', 'y': 'survival'}}
],
'scales': {'y': {'domain': [0, 1]}}
}
Benefits:
- Composable: Combine multiple marks/layers
- Reproducible: Grammar specs are JSON (version control, templates)
- Flexible: Easy to modify specific aspects
- Publication-grade: Based on Leland Wilkinson's Grammar of Graphics
When to Use G2 vs Plotly
Use G2 When:
✅ Complex multi-layer compositions (e.g., forest plot with CI bars + diamonds) ✅ Custom chart types not available in Plotly ✅ Multi-panel figures with faceting ✅ Template-driven workflows (same grammar, different data) ✅ Publication figures requiring precise control ✅ Research papers with custom requirements
Use Plotly When:
✅ Standard charts (bar, line, scatter) ✅ Interactive dashboards (web-based, hover, zoom) ✅ Quick prototyping (simpler API) ✅ Built-in chart types work out of the box
Decision Tree:
Does Plotly have a built-in chart type that works?
├─ YES → Use Plotly (faster, simpler)
└─ NO → Do you need custom composition?
├─ YES → Use G2 (grammar-based)
└─ NO → Use drawsvg (pure Python SVG)
Available Medical Grammars
1. Forest Plot
from medical_grammars import forest_plot_grammar
grammar = forest_plot_grammar(
studies=['Study A', 'Study B', 'Study C'],
estimates=[0.80, 0.74, 0.92],
lower_ci=[0.73, 0.65, 0.86],
upper_ci=[0.87, 0.85, 0.99],
weights=[84, 60, 35], # For sizing
null_value=1.0,
log_scale=True,
title="Meta-Analysis Results"
)
Features:
- Confidence interval bars with transparency
- Diamond-shaped point estimates sized by weight
- Null hypothesis line (dashed)
- Log scale for ratio metrics
- Automatic transposition (studies on y-axis)
2. Kaplan-Meier Survival Curve
from medical_grammars import kaplan_meier_grammar
grammar = kaplan_meier_grammar(
time_data=[
[0, 6, 12, 18, 24], # Treatment
[0, 6, 12, 18, 24] # Control
],
survival_data=[
[1.0, 0.90, 0.82, 0.78, 0.75], # Treatment
[1.0, 0.85, 0.72, 0.65, 0.58] # Control
],
group_names=['Treatment', 'Control'],
title="Overall Survival"
)
Features:
- Step function (hv shape) for survival curves
- Shaded area below curves (10% opacity)
- Colorblind-safe treatment/control colors
- Y-axis fixed at [0, 1]
3. Grouped Bar Chart
from medical_grammars import grouped_comparison_grammar
grammar = grouped_comparison_grammar(
categories=['Primary', 'Secondary', 'Safety'],
groups=['Treatment', 'Placebo'],
values=[
[12.3, 8.5, 3.2], # Treatment
[18.7, 14.2, 2.8] # Placebo
],
title="Trial Results"
)
Features:
- Dodged bars for side-by-side comparison
- Colorblind-safe group colors
- Rounded corners (2px radius)
4. Multi-Panel Figure
from medical_grammars import multi_panel_grammar
grammar = multi_panel_grammar(
data=[
{'x': 0, 'y': 10, 'category': 'A', 'panel': 'Baseline'},
{'x': 1, 'y': 12, 'category': 'A', 'panel': 'Baseline'},
{'x': 0, 'y': 15, 'category': 'A', 'panel': 'Follow-up'},
# ...
],
x_field='x',
y_field='y',
color_field='category',
facet_field='panel',
title="Longitudinal Analysis"
)
Features:
- Faceted subplots (small multiples)
- Points + smoothed lines
- Shared scales across panels
- Categorical color palette
5. Scatter with Regression
from medical_grammars import scatter_regression_grammar
grammar = scatter_regression_grammar(
x_data=[25, 30, 35, 40, 45],
y_data=[2800, 2200, 1800, 1200, 900],
regression_line=True,
title="LVEF vs NT-proBNP Correlation"
)
Features:
- Scatter points with transparency
- Optional regression line (dashed)
- Optional grouping by category
6. Heatmap
from medical_grammars import heatmap_grammar
grammar = heatmap_grammar(
data=[
{'marker1': 'BNP', 'marker2': 'Troponin', 'correlation': 0.65},
# ...
],
x_field='marker1',
y_field='marker2',
value_field='correlation',
title="Biomarker Correlations"
)
Features:
- Cell-based heatmap
- Sequential color scale
- White gridlines between cells
CLI Usage
Quick Commands
# List available templates
python g2_cli.py list-templates
# Generate forest plot
python g2_cli.py forest \
--studies "DAPA-HF,EMPEROR-Reduced,VICTORIA" \
--estimates "0.74,0.75,0.90" \
--lower "0.65,0.65,0.82" \
--upper "0.85,0.86,0.98" \
-o forest.png
# Generate Kaplan-Meier from data file
python g2_cli.py kaplan --data survival.json -o km.svg --format svg
# Generate grouped bars from data
python g2_cli.py grouped --data trial_results.json -o bars.png
# Generate all demo charts
python g2_cli.py demo --all
Data File Formats
Kaplan-Meier (survival.json):
{
"groups": ["Treatment", "Control"],
"time": [
[0, 6, 12, 18, 24],
[0, 6, 12, 18, 24]
],
"survival": [
[1.0, 0.90, 0.82, 0.78, 0.75],
[1.0, 0.85, 0.72, 0.65, 0.58]
]
}
Grouped Bars (trial_results.json):
{
"categories": ["Primary", "Secondary", "Safety"],
"groups": ["Treatment", "Placebo"],
"values": [
[12.3, 8.5, 3.2],
[18.7, 14.2, 2.8]
]
}
Custom Grammars
Build custom charts from scratch using the grammar API:
from grammar_renderer import G2Chart
chart = G2Chart(width=800, height=600)
# Set data
chart.data([
{'category': 'A', 'value': 23},
{'category': 'B', 'value': 45},
{'category': 'C', 'value': 31}
])
# Add interval mark (bars)
chart.add_mark(
'interval',
encode={'x': 'category', 'y': 'value'},
style={'fill': '#1e3a5f', 'radius': 2}
)
# Configure scales
chart.scale('y', {'nice': True})
# Set axes
chart.axis('x', title='Category')
chart.axis('y', title='Value', grid=True)
# Render
chart.render('custom.png')
Grammar Components
| Component | Description | Example |
|---|---|---|
| data | Chart data | chart.data([{...}, {...}]) |
| marks | Geometry layers | chart.add_mark('point', encode={...}) |
| scales | Data-to-visual mapping | chart.scale('y', {'type': 'log'}) |
| coordinate | Coordinate transformation | chart.coordinate('transpose') |
| axes | Axis configuration | chart.axis('x', title='Time') |
| legend | Legend configuration | chart.legend(position='top') |
Mark Types
| Mark | Description | Use Case |
|---|---|---|
point |
Scatter points | Scatter plots, estimates |
line |
Lines | Trends, survival curves |
interval |
Bars/rectangles | Bar charts, CI intervals |
area |
Filled areas | Area under curve |
cell |
Grid cells | Heatmaps |
text |
Text labels | Annotations |
rect |
Rectangles | Custom shapes |
Integration with Visual System
G2 charts automatically use design tokens from visual-design-system:
# Colors (from tokens/colors.json)
COLORS = {
'primary': '#1e3a5f',
'categorical': ['#4477AA', '#66CCEE', '#228833', ...],
'treatment_control': ['#0077bb', '#ee7733']
}
# Typography (from tokens/typography.json)
TYPOGRAPHY = {
'family': 'Helvetica, Arial, sans-serif',
'sizes': {
'title': 14,
'axis': 8,
'legend': 9
}
}
# Spacing (from tokens/spacing.json)
PADDING = [40, 60, 40, 60] # top, right, bottom, left
All grammars apply these tokens automatically for consistency with Plotly, drawsvg, and Satori outputs.
Output Formats
PNG (Default)
chart.render('output.png', format='png')
- Publication quality
- 800×600px default (configurable)
- Suitable for papers, presentations
SVG (Vector)
chart.render('output.svg', format='svg')
- Scalable vector graphics
- Editable in Illustrator/Inkscape
- Smaller file size
- Perfect for journals requiring vector formats
Demo Charts
Generate all demo charts:
cd skills/cardiology/visual-design-system/g2_charts
python examples/demo_charts.py --all
Generated:
demo_forest_plot.png- Meta-analysis with 5 trialsdemo_kaplan_meier.png- Treatment vs control survivaldemo_grouped_bars.png- Trial outcomes comparisondemo_scatter.png- EF vs BNP correlationdemo_heatmap.png- Biomarker correlation matrix
Plus grammar JSON files for each chart (for reference/modification).
Directory Structure
g2_charts/
├── SKILL.md # This file
├── package.json # npm dependencies
├── node_modules/ # G2, canvas, jsdom
├── renderer.js # Node.js renderer
├── grammar_renderer.py # Python API
├── medical_grammars.py # Pre-built grammars
├── g2_cli.py # CLI interface
├── templates/ # JSON grammar templates
│ ├── forest_plot.json
│ ├── kaplan_meier.json
│ ├── grouped_bars.json
│ ├── multi_panel.json
│ └── consort_flow.json
├── examples/
│ └── demo_charts.py # Demo generator
└── outputs/ # Generated charts
├── demo_forest_plot.png
├── demo_kaplan_meier.png
└── ...
G2 vs Plotly Comparison
| Feature | G2 | Plotly |
|---|---|---|
| API Style | Declarative (grammar) | Imperative (method calls) |
| Composability | ⭐⭐⭐⭐⭐ Excellent | ⭐⭐⭐ Good |
| Custom Charts | ⭐⭐⭐⭐⭐ Full control | ⭐⭐⭐ Limited by built-ins |
| Interactivity | ⭐⭐ Static exports | ⭐⭐⭐⭐⭐ Built-in zoom/hover |
| Learning Curve | ⭐⭐ Steeper (grammar concepts) | ⭐⭐⭐⭐ Easier (familiar API) |
| Speed | ⭐⭐⭐⭐ Fast | ⭐⭐⭐⭐ Fast |
| File Size | ⭐⭐⭐⭐ Small | ⭐⭐⭐ Larger |
| Publication Quality | ⭐⭐⭐⭐⭐ Excellent | ⭐⭐⭐⭐ Very good |
| Forest Plots | ⭐⭐⭐⭐⭐ Native grammar | ⭐⭐⭐ Manual construction |
| Multi-Panel | ⭐⭐⭐⭐⭐ Faceting built-in | ⭐⭐⭐ Subplots |
Bottom Line:
- Simple charts: Plotly (faster, easier)
- Complex compositions: G2 (more flexible, composable)
- Both work: Use whichever you prefer
Troubleshooting
Node.js not found
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
npm packages not installed
cd skills/cardiology/visual-design-system/g2_charts
npm install
Canvas rendering errors
# Install canvas dependencies (Linux)
sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
# Reinstall canvas
npm rebuild canvas
Python import errors
# Ensure you're in the right directory
cd skills/cardiology/visual-design-system/g2_charts
# Or add to PYTHONPATH
export PYTHONPATH="${PYTHONPATH}:/path/to/visual-design-system/g2_charts"
Grammar Cookbook
Example 1: Add Annotations to Forest Plot
grammar = forest_plot_grammar(...)
# Add vertical line at HR=1.5
grammar['annotations'] = [
{
'type': 'line',
'encode': {
'x': 1.5,
'style': {
'stroke': '#ff9800',
'strokeWidth': 2,
'lineDash': [4, 4]
}
}
}
]
Example 2: Customize Colors
grammar = kaplan_meier_grammar(...)
# Override default colors
grammar['scales']['color'] = {
'range': ['#e74c3c', '#3498db', '#2ecc71']
}
Example 3: Add Confidence Bands
chart.add_mark(
'area',
encode={
'x': 'time',
'y': ['lower_ci', 'upper_ci'],
'color': 'group'
},
style={'fillOpacity': 0.2}
)
References
Last Updated: 2026-01-01 Maintainer: Dr. Shailesh Singh
Didn't find tool you were looking for?