Metadata-Version: 2.4
Name: bottleviz
Version: 0.2.4
Summary: A modern Python data visualization library with smart defaults
Author-email: Pavan Paari <pavan.paari@dhsit.co.uk>
License: MIT
Keywords: visualization,plotting,matplotlib,seaborn,data-science
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.18.0
Requires-Dist: pandas>=1.0.0
Requires-Dist: matplotlib>=3.0.0
Requires-Dist: requests>=2.25.0
Requires-Dist: scipy>=1.6.0
Requires-Dist: statsmodels>=0.14.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black>=21.0; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: jupyter; extra == "dev"
Requires-Dist: ipython; extra == "dev"
Provides-Extra: plotly
Requires-Dist: plotly>=5.0.0; extra == "plotly"
Provides-Extra: datashader
Requires-Dist: datashader>=0.13.0; extra == "datashader"
Provides-Extra: network
Requires-Dist: networkx>=2.0; extra == "network"
Provides-Extra: treemap
Requires-Dist: squarify>=0.4.0; extra == "treemap"
Provides-Extra: all
Requires-Dist: plotly>=5.0.0; extra == "all"
Requires-Dist: datashader>=0.13.0; extra == "all"
Requires-Dist: networkx>=2.0; extra == "all"
Requires-Dist: squarify>=0.4.0; extra == "all"
Requires-Dist: scipy>=1.6.0; extra == "all"
Requires-Dist: polars>=0.19.0; extra == "all"
Provides-Extra: ai
Requires-Dist: openai>=1.0.0; extra == "ai"
Requires-Dist: anthropic>=0.18.0; extra == "ai"
Requires-Dist: ollama>=0.1.0; extra == "ai"
Dynamic: license-file

# BottleViz

**A modern Python data visualization library with smart defaults.**

BottleViz addresses the gaps in Matplotlib, Seaborn, and Plotly by providing a simplified, intuitive API with beautiful defaults out of the box, excellent performance with large datasets, and seamless integration with pandas and polars.

**Now with 55 plot types, including full Seaborn-style statistical visualizations!**

## Key Features

### 1. **Simplified API**
One function handles most use cases:
```python
import bottleviz as vz
vz.plot(df, x='column1', y='column2')  # All in one line!
```

vs. Matplotlib:
```python
fig, ax = plt.subplots()
ax.scatter(df['column1'], df['column2'])
ax.set_xlabel('column1')
ax.set_ylabel('column2')
```

### 2. **Intelligent Plot Type Detection**
BottleViz automatically chooses the right plot type based on your data:
- **Basic**: Scatter, line, histogram, bar, pie, area
- **Distributions**: Box, violin, **boxen**, KDE, **rug**, **strip**, **swarm**
- **Relationships**: Scatter, hexbin, **jointplot**, **pairplot**
- **Time Series**: Line, **lagplot**, **autocorrelation**
- **Statistical Diagnostics**: **Q-Q plot**, **residual plot**
- **Multivariate**: Heatmap, contour, **parallel coordinates**, **andrews curves**, **radviz**
- **Advanced**: Sankey, Sunburst, Treemap, Network, Candlestick
- **3D**: 3D scatter, surface, wireframe, contour, quiver, voxels
- **Geographic**: Choropleth, Scatter Geo, Flow Maps, Tile Maps, **Cartogram**

```python
vz.plot(df)  # Auto-detects appropriate visualization!
```

### 3. **Beautiful Defaults**
Stunning visualizations with zero configuration:
- Modern color palettes (colorblind-friendly)
- Professional typography
- Optimized layout and sizing
- Publication-ready styles
- Dark mode support

```python
vz.set_style('dark')  # Multiple presets available
vz.plot(df)  # Automatically looks great
```

### 4. **AI-Powered Suggestions** (Optional)
Get intelligent plot recommendations from AI models:

**Cloud providers:**
- OpenAI GPT-4o, GPT-4o-mini
- Anthropic Claude 3 (Haiku, Sonnet, Opus)

**Local models:**
- Ollama (run models locally: llama3.2, mistral, codellama, etc.)

```python
# Use AI to suggest the best visualization
vz.suggest_plots(df, ai=True, api_key="your-api-key")

# Or with local Ollama (no API key needed)
vz.suggest_plots(df, ai=True, ai_provider='ollama', model='llama3.2:1b')

# Result includes AI's reasoning and exact code to generate the plot
```

### 4. **Excellent Performance**
Optimized for large datasets:
- Smart downsampling for >10k points
- Optional GPU acceleration
- Datashader backend for millions of points
- Lazy evaluation where applicable

```python
vz.plot(large_df)  # Handles 1M+ rows smoothly
```

### 5. **Seamless Dataframe Integration**
Works perfectly with pandas, polars, and more:
```python
vz.plot(df, x='date', y='sales')
vz.plot(polars_df, x='col1', y='col2')
```

### 6. **Unified Interface**
One consistent API across all plot types:
```python
vz.plot(df, x='col1', y='col2', kind='scatter')  # Same interface
vz.plot(df, x='col1', y='col2', kind='line')
vz.plot(df, x='col1', y='col2', kind='bar')
vz.plot(df, kind='hist')  # Even works without x/y
```

### 7. **Advanced Visualizations**
Explore complex data relationships with specialized chart types:

**Sankey Diagrams** - Flow between stages/categories
```python
vz.plot(flow_data, kind='sankey', source='from', target='to', value='count')
```
*Requires: `networkx`*

**Sunburst Charts** - Hierarchical radial layouts
```python
vz.plot(hierarchy_data, kind='sunburst', path=['region', 'city'], value='sales')
```
*Optional: `squarify` for treemap variant*

**Treemaps** - Hierarchical rectangular layouts
```python
vz.plot(hierarchy_data, kind='treemap', path=['region', 'city'], value='sales')
```
*Requires: `squarify`*

**Network Graphs** - Visualize relationships and connections
```python
vz.plot(edges, kind='network', source='node1', target='node2', layout='spring')
```
*Requires: `networkx`*

**Candlestick Charts** - Financial OHLC time series
```python
vz.plot(stock_data, x='date', kind='candlestick', open='open', high='high', low='low', close='close')
```

**3D Visualizations** - Comprehensive 3D plotting suite
```python
# Surface plot (points connected by planes)
fig, ax = vz.plot_3d_surface(X, Y, Z, title='Surface', cmap='viridis')

# Wireframe mesh
fig, ax = vz.plot_3d_wireframe(X, Y, Z, title='Wireframe')

# Triangular surface (for scattered data)
fig, ax = vz.plot_3d_trisurf(x, y, z, title='Triangular Surface')

# Contour lines and filled contours
fig, ax = vz.plot_3d_contour(X, Y, Z, levels=15)
fig, ax = vz.plot_3d_contourf(X, Y, Z, levels=20)

# Vector field (arrows)
fig, ax = vz.plot_3d_quiver(X, Y, Z, U, V, W, title='Vector Field')

# 3D stem plot
fig, ax = vz.plot_3d_stem(x, y, z, title='3D Stem')

# 3D bar chart
fig, ax = vz.plot_3d_bar(x, y, z, dx, dy, dz, title='3D Bars')

# 3D voxel/volume rendering
fig, ax = vz.plot_3d_voxels(voxel_array, title='3D Voxels')

# Advanced: Create custom 3D figure and add multiple elements
fig, ax = vz.figure3d(title='Custom 3D Plot')
ax.plot_surface(X, Y, Z, cmap='plasma')
ax.contour(X, Y, Z, levels=10)
vz.show()
```

All 3D functions support full matplotlib customization via `**kwargs`.

## Installation

```bash
# Basic installation
pip install bottleviz

# With all optional backends
pip install bottleviz[all]

# Just pandas/numpy + matplotlib
pip install bottleviz

# For interactive plots (Plotly)
pip install bottleviz[plotly]

# For massive datasets (Datashader)
pip install bottleviz[datashader]

# For AI-powered suggestions
pip install bottleviz[ai]  # Installs openai, anthropic, ollama packages
```

## Quick Start

```python
import bottleviz as vz
import pandas as pd
import numpy as np

# Create sample data
df = pd.DataFrame({
    'x': np.random.randn(1000),
    'y': np.random.randn(1000),
    'category': np.random.choice(['A', 'B', 'C'], 1000),
    'value': np.random.randint(0, 100, 1000)
})

# Simple plot - auto-detects scatter
vz.plot(df, x='x', y='y')

# Bar chart with categories
vz.plot(df, x='category', y='value', kind='bar')

# Histogram
vz.plot(df, kind='hist', x='value')

# Time series
dates = pd.date_range('2024-01-01', periods=100)
ts_df = pd.DataFrame({
    'date': dates,
    'price': np.random.randn(100).cumsum() + 100
})
vz.plot(ts_df, x='date', y='price')  # Auto-detects line plot

# Change style
vz.set_style('dark')
vz.plot(df, x='x', y='y')

# Get suggestions
vz.suggest_plots(df)

# Quick dashboard
vz.visualize(df)
```

## New Plot Types Gallery

### Stacked & Grouped Bar Charts
```python
# Stacked bar (shows composition)
vz.plot(df, x='category', y=['sales_2023', 'sales_2024'], kind='stacked_bar')

# Grouped bar (side-by-side comparison)
vz.plot(df, x='group', y=['A', 'B', 'C'], kind='grouped_bar')
```

### 2D Density & Bin Plots
```python
# Hexbin for large scatter datasets
vz.plot(large_df, x='x', y='y', kind='hexbin', gridsize=50, cmap='viridis')

# Step plot for discrete/constant changes
vz.plot(df, x='time', y='value', kind='step', where='pre')

# Fill between for confidence intervals
vz.plot(df, x='time', y='value', y_lower='ci_lower', y_upper='ci_upper', kind='fill_between')
vz.plot(df, x='time', y='value', kind='fill_between')  # fills to zero
```

### 2D Contour & Grid Plots
```python
# 2D Contour lines
x = np.linspace(-3, 3, 50)
y = np.linspace(-3, 3, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
grid_data = pd.DataFrame({'x': X.flatten(), 'y': Y.flatten(), 'z': Z.flatten()})
vz.plot(grid_data, x='x', y='y', z='z', kind='contour')
vz.plot(grid_data, x='x', y='y', z='z', kind='contour', filled=True)  # filled contours

# Pcolormesh for flexible gridded data
vz.plot(grid_data, x='x', y='y', value='z', kind='pcolormesh', cmap='plasma')
```

### Heatmaps with Annotations
Heatmaps support text annotations in each cell:
```python
# Correlation matrix with values
corr = df.corr()
vz.plot(corr, kind='heatmap', cmap='RdYlBu', center=0,
        annot=True, fmt='.2f', annot_fontsize=9)
```

### Vector & Sparse Data
```python
# 2D Quiver (vector field)
vz.plot(vector_df, x='x', y='y', u='u', v='v', kind='quiver')

# Streamplot (flow lines) -自动 handles both gridded and long-form data
vz.plot(stream_df, x='x', y='y', u='u', v='v', kind='streamplot',
        color='speed', cmap='viridis', density=2)

# Spy plot for sparse matrices
sparse_matrix = np.random.choice([0, 1], size=(100, 100), p=[0.95, 0.05])
vz.plot(pd.DataFrame(sparse_matrix), kind='spy', markersize=2)
```

### Contours on Scattered Data
For data that is not on a regular grid, use tricontour variants:
```python
# Generate scattered points
n = 500
x = np.random.uniform(-3, 3, n)
y = np.random.uniform(-3, 3, n)
z = np.sin(x) * np.cos(y) + np.random.randn(n)*0.1
scattered = pd.DataFrame({'x': x, 'y': y, 'z': z})

# Tricontour (lines)
vz.plot(scattered, x='x', y='y', z='z', kind='tricontour', levels=15)

# Tricontourf (filled)
vz.plot(scattered, x='x', y='y', z='z', kind='tricontourf', levels=20)
```

### Special Coordinate Systems
```python
# Polar plots (radial)
theta = np.linspace(0, 2*np.pi, 100)
r = 1 + np.cos(2*theta)
polar_df = pd.DataFrame({'theta': theta, 'r': r})
vz.plot(polar_df, theta='theta', r='r', kind='polar')
vz.plot(polar_df, theta='theta', r='r', kind='polar', fill=True, alpha=0.5)
```

### Tables & Event Timeline
```python
# Table visualization
vz.plot(df, kind='table', max_rows=10, fontsize=9)

# Event plot for sequences (R&D, healthcare events)
event_data = pd.DataFrame({
    'patient_id': [1, 2, 3],
    'diagnosis': [1, 0, 1],
    'treatment': [1, 1, 0],
    'recovery': [0, 1, 1]
})
vz.plot(event_data, columns=['diagnosis', 'treatment', 'recovery'], kind='eventplot')
```

### Financial & Project Charts

```python
# Waterfall chart (profit walk, bridge charts)
waterfall_data = pd.DataFrame({
    'category': ['Starting', 'Revenue', 'Cost', 'Investment', 'Return'],
    'value': [100, 50, -30, -20, 40]
})
vz.plot(waterfall_data, x='category', y='value', kind='waterfall')

# Gantt chart (project timelines)
gantt_data = pd.DataFrame({
    'task': ['Design', 'Development', 'Testing', 'Deployment'],
    'start': ['2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01'],
    'end': ['2024-01-31', '2024-03-01', '2024-03-31', '2024-04-15']
})
vz.plot(gantt_data, task='task', start='start', end='end', kind='gantt')

# OHLC with volume (financial candlestick + volume)
ohlc_data = pd.DataFrame({
    'date': pd.date_range('2024-01-01', periods=20, freq='D'),
    'open': np.random.rand(20) * 100 + 100,
    'high': np.random.rand(20) * 110 + 100,
    'low': np.random.rand(20) * 90 + 100,
    'close': np.random.rand(20) * 100 + 100,
    'volume': np.random.randint(1000, 5000, 20)
})
ohlc_data['high'] = ohlc_data[['open','close','high']].max(axis=1)
ohlc_data['low'] = ohlc_data[['open','close','low']].min(axis=1)
vz.plot(ohlc_data, x='date', open='open', high='high', low='low',
       close='close', volume='volume', kind='ohlc_volume')
```

### Statistical & Exploratory Data Analysis (EDA) Plots

BottleViz includes a comprehensive suite of statistical and EDA plots for in-depth data exploration:

**Pair Plot** - Scatter matrix with histograms/KDE on diagonal
```python
# Multi-variable scatter matrix
vz.plot(df, kind='pairplot', columns=['x1', 'x2', 'x3', 'x4'])
# With grouping (uses color for different classes)
vz.plot(df, kind='pairplot', columns=['x1', 'x2', 'x3'], hue='category')
```

**Joint Plot** - Scatter plot with marginal distributions (histogram or KDE)
```python
# Basic joint plot
vz.plot(df, x='x', y='y', kind='jointplot')

# With KDE margins
vz.plot(df, x='x', y='y', kind='jointplot', marginal_kind='kde')

# With hexbin for the main plot
vz.plot(df, x='x', y='y', kind='jointplot', joint_kind='hexbin')
```

**Boxen Plot** - Letter-value box plots (enhanced box plot showing more distribution details)
```python
vz.plot(df, x='category', y='value', kind='boxen')
vz.plot(df, x='category', y='value', kind='boxen', k_depth='profound')  # More detail
```

**Rug Plot** - Marginal tick marks showing distribution along one axis
```python
vz.plot(df, x='value', kind='rug', height=0.2)
vz.plot(df, x='value', kind='rug', color='blue', alpha=0.5)
```

**Strip Plot** - Categorical scatter plot with jitter to prevent overplotting
```python
vz.plot(df, x='category', y='value', kind='strip', jitter=0.2)
vz.plot(df, x='category', y='value', kind='strip', hue='subcategory')
```

**Swarm Plot** - Non-overlapping categorical scatter (like strip but points don't overlap)
```python
vz.plot(df, x='category', y='value', kind='swarm')
vz.plot(df, x='category', y='value', kind='swarm', size=3, alpha=0.7)
```

**Q-Q Plot** - Quantile-Quantile plot for normality testing
```python
# Compare distribution to normal
vz.plot(df, x='residuals', kind='qqplot', dist='norm')

# Compare to other distributions
vz.plot(df, x='data', kind='qqplot', dist='uniform')
```

**Residual Plot** - Plot residuals vs fitted values for regression diagnostics
```python
vz.plot(df, x='predictor', y='response', kind='residualplot', order=1)
vz.plot(df, x='x', y='y', kind='residualplot', lowess=True)  # With LOWESS smooth
```

**Autocorrelation Plot (ACF)** - Shows correlation of time series with its lags
```python
vz.plot(ts_df, x='value', kind='autocorrelation', lags=50)
vz.plot(ts_df, x='value', kind='autocorrelation', lags=30, alpha=0.05)  # 95% CI
```

**Lag Plot** - Scatter plot of time series vs its lag (check for autocorrelation)
```python
vz.plot(ts_df, x='value', kind='lagplot', lag=1)    # Lag-1 plot
vz.plot(ts_df, x='value', kind='lagplot', lag=12)  # Seasonal lag
```

**Andrews Curves** - Visualize multivariate data as continuous functions (for classification)
```python
# Each sample becomes a curve; curves group by class
vz.plot(df, x='species', columns=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'],
        kind='andrews_curves')
```

**Parallel Coordinates** - Parallel axes showing multivariate observations
```python
vz.plot(df, x='class', columns=['feat1', 'feat2', 'feat3', 'feat4'],
        kind='parallel_coordinates', alpha=0.5)
```

**RadViz** - Radial coordinate system for multivariate visualization
```python
vz.plot(df, x='species', columns=['x1', 'x2', 'x3', 'x4'],
        kind='radviz', alpha=0.7)
```

**Notes:**
- Most statistical plots support optional `scipy` for enhanced features (KDE, distributions)
- Pair plot and joint plot can be memory intensive for very large datasets (>10k rows)
- Consider using `sample` parameter for large data: `vz.plot(df.sample(5000), kind='pairplot', ...)`

**Demo**: See `examples/demo_statistical_plots.py` for complete examples of all these plot types.

### Geographic & Map Visualizations

```python
# Requires geopandas
import bottleviz as vz
# gdf must have a geometry column (GeoSeries or shapely geometries)
vz.plot(gdf, kind='choropleth', geometry='geometry', value='population',
        title='Population by Region', cmap='viridis')
```

**Scatter Geo** - Scatter plot overlaid on geographic coordinates.

```python
vz.plot(df, kind='scatter_geo', lat='latitude', lon='longitude',
        value='temperature', title='Temperature by Location',
        cmap='plasma', markersize=50, alpha=0.7)
```

**Flow Maps** - Show movement/flows between origins and destinations using lines.

```python
vz.plot(df, kind='flow_map', origin_lat='olat', origin_lon='olon',
        dest_lat='dlat', dest_lon='dlon', flow='volume',
        title='Migration Flows Between Cities', color='#2196F3')
```

**Tile Maps** - Choropleth with a basemap tile layer (e.g., OpenStreetMap).

```python
# Requires contextily
import geopandas as gpd
import contextily as ctx
gdf = gpd.GeoDataFrame(df, geometry='geometry').to_crs(epsg=3857)
vz.plot(gdf, kind='tile_map', value='density', title='Population Density',
        tile_source=ctx.providers.OpenStreetMap.Mapnik)
```

**Cartograms** - Distort geographic areas proportionally to a data value.

```python
vz.plot(gdf, kind='cartogram', value='population',
        title='Population Cartogram', color='#4CAF50')
```

## API Reference

### Main Functions

#### `vz.plot(data, x=None, y=None, kind=None, **kwargs)`
Core plotting function with smart defaults.

**Parameters:**
- `data`: DataFrame, Series, ndarray, list, or dict
- `x`: Column name for x-axis (optional)
- `y`: Column name(s) for y-axis (optional)
- `kind`: Plot type ('scatter', 'line', 'bar', 'stacked_bar', 'grouped_bar', 'hist', 'box', 'violin', 'heatmap', 'pcolormesh', 'pie', 'area', 'kde', '3d', 'stem', 'errorbar', 'sankey', 'sunburst', 'treemap', 'network', 'candlestick', 'hexbin', 'step', 'fill_between', 'contour', 'quiver', 'spy', 'polar', 'table', 'eventplot', 'waterfall', 'gantt', 'ohlc_volume', 'scatter_geo', 'cartogram', 'choropleth', 'flow_map', 'tile_map', **'pairplot'**, **'jointplot'**, **'boxen'**, **'rug'**, **'strip'**, **'swarm'**, **'qqplot'**, **'residualplot'**, **'autocorrelation'**, **'lagplot'**, **'andrews_curves'**, **'parallel_coordinates'**, **'radviz'**, **'streamplot'**, **'tricontour'**, **'tricontourf'**)
- `**kwargs`: Additional arguments (title, xlabel, ylabel, etc.)

**Examples:**
```python
vz.plot(df, x='col1', y='col2')                    # Auto-detects scatter
vz.plot(df, x='col1', y='col2', kind='line')       # Force line
vz.plot(df, kind='hist')                           # Histogram of all numeric columns
vz.plot(df, x='category', y='value', kind='bar')  # Bar chart

# Statistical & EDA plots
vz.plot(df, kind='pairplot', columns=['x1', 'x2', 'x3'])
vz.plot(df, x='x', y='y', kind='jointplot')
vz.plot(df, x='category', y='value', kind='boxen')
vz.plot(df, x='value', kind='qqplot')
vz.plot(ts_df, x='value', kind='autocorrelation', lags=50)

# Advanced scientific plots
vz.plot(stream_df, x='x', y='y', u='u', v='v', kind='streamplot')
vz.plot(scattered_df, x='x', y='y', z='z', kind='tricontour', levels=15)
```

#### `vz.quickplot(*args, **kwargs)`
Ultra-simple one-liner plotting.

```python
vz.quickplot([1,2,3,4,5])                      # Line plot from list
vz.quickplot(x=[1,2,3], y=[4,5,6])             # Named lists
vz.quickplot(df)                               # Auto-visualize first two numeric columns
```

#### `vz.subplots(n_rows=2, n_cols=2, sharex=False, sharey=False, figsize=(12,8), title=None, **kwargs)`
Create a figure with multiple subplots. Returns `(fig, axes)`.

```python
fig, axes = vz.subplots(2, 3, sharex=True, figsize=(15, 8))
axes[0,0].plot(x, y)
axes[0,1].scatter(x, y2)
vz.show()
```

#### `vz.inset(x, y, kind='line', title=None, xlabel=None, ylabel=None, figsize=None, inset_bounds=(0.6, 0.6, 0.35, 0.35), xlim=None, ylim=None, loc='upper right', borderpad=1, **kwargs)`
Create a main plot with an inset axes for zoomed detail. Returns `(fig, main_ax, inset_ax)`.

```python
fig, main_ax, inset_ax = vz.inset(
    x=time_series, y=data,
    kind='line',
    title='Time Series with Zoomed Inset',
    xlim=(2, 4), ylim=(-0.5, 0.5)  # Limits applied to inset
)
# main_ax already has the line plot; customize inset_ax as needed
vz.show()
```

#### `vz.figure(figsize=None, **kwargs)`
Create a simple figure with a single axes. Returns `(fig, ax)`.

```python
fig, ax = vz.figure(figsize=(10, 6))
ax.plot(x, y)
ax.set_xlabel('X')
ax.set_ylabel('Y')
vz.show()
```

#### `vz.visualize(data, columns=None, plot_type='auto', max_plots=6, **kwargs)`
Create a multi-panel dashboard for exploratory analysis.

```python
vz.visualize(df)                    # Dashboard with all numeric columns
vz.visualize(df, columns=['x','y','z'])  # Specific columns only
vz.visualize(df, plot_type='dist')  # Distribution plots only
```

#### `vz.suggest_plots(data, ai=False, ai_provider=None, api_key=None, **ai_kwargs)`
Get recommendations for visualizations, optionally using AI.

```python
recs = vz.suggest_plots(df)
print(recs)
#       type    x    y                      rationale              example_code
# 0     hist   x  None  Distribution of 'x' - shows...  vz.plot(df, x='x')
# 1   scatter   x    y         Relationship between...  vz.plot(df, x='x', y='y')

# With AI enhancement (OpenAI)
recs = vz.suggest_plots(df, ai=True, api_key="your-openai-key")

# With local Ollama model
recs = vz.suggest_plots(df, ai=True, ai_provider='ollama', model='llama3.2:1b')
```

#### `vz.report(data, show_plots=False)`
Generate a comprehensive report.

```python
report = vz.report(df)  # Text report
report = vz.report(df, show_plots=True)  # Report + dashboard figure
```

#### `vz.explore(data, mode='auto')`
Smart exploratory data analysis.

```python
vz.explore(df)                      # Auto-choose best visualizations
vz.explore(df, mode='distribution') # Distribution plots only
vz.explore(df, mode='relationship') # Correlation plots
```

#### `vz.show_plotly(data, kind, **kwargs)`
Create an interactive Plotly visualization and return as HTML string.

```python
# Generate interactive HTML for a scatter plot
html = vz.show_plotly(df, x='x', y='y', kind='scatter')

# Save to file
with open('plot.html', 'w') as f:
    f.write(html)

# Or display in Jupyter notebook
from IPython.display import HTML
HTML(html)
```

#### `vz.save_plotly(data, filepath, kind, **kwargs)`
Create an interactive Plotly visualization and save directly to HTML file.

```python
# Save interactive plot to HTML file
vz.save_plotly(df, 'interactive_scatter.html', x='x', y='y', kind='scatter')

# With additional customization
vz.save_plotly(df, 'interactive_hist.html', x='value', kind='hist',
               title='Interactive Histogram', nbins=50)
```

### 3D Plotting Functions

BottleViz provides specialized functions for true 3D visualizations that work with array data:

#### `vz.plot_3d_surface(X, Y, Z, title=None, xlabel='X', ylabel='Y', zlabel='Z', **kwargs)`
Create a 3D surface plot (mesh grid connected as a continuous surface).

```python
import numpy as np
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))

fig, ax = vz.plot_3d_surface(X, Y, Z, title='Surface Plot', cmap='viridis')
vz.show()
```

#### `vz.plot_3d_wireframe(X, Y, Z, title=None, xlabel='X', ylabel='Y', zlabel='Z', **kwargs)`
Create a 3D wireframe plot (shows grid structure with lines).

```python
fig, ax = vz.plot_3d_wireframe(X, Y, Z, title='Wireframe', color='blue', linewidth=0.5)
vz.show()
```

#### `vz.plot_3d_trisurf(x, y, z, title=None, xlabel='X', ylabel='Y', zlabel='Z', **kwargs)`
Triangular surface plot for irregularly scattered data (automatic triangulation).

```python
x_rand = np.random.uniform(-5, 5, 500)
y_rand = np.random.uniform(-5, 5, 500)
z_rand = np.sin(np.sqrt(x_rand**2 + y_rand**2))
fig, ax = vz.plot_3d_trisurf(x_rand, y_rand, z_rand, cmap='plasma')
vz.show()
```

#### `vz.plot_3d_contour(X, Y, Z, title=None, xlabel='X', ylabel='Y', levels=15, **kwargs)`
3D contour lines (projected onto 3D surface).

```python
fig, ax = vz.plot_3d_contour(X, Y, Z, levels=20, cmap='coolwarm')
vz.show()
```

#### `vz.plot_3d_contourf(X, Y, Z, title=None, xlabel='X', ylabel='Y', levels=15, **kwargs)`
Filled 3D contour plot.

```python
fig, ax = vz.plot_3d_contourf(X, Y, Z, levels=20, cmap='RdYlBu')
vz.show()
```

#### `vz.plot_3d_quiver(X, Y, Z, U, V, W, title=None, xlabel='X', ylabel='Y', zlabel='Z', **kwargs)`
3D quiver plot (vector field with arrows).

```python
# Create grid
x = y = z = np.linspace(-2, 2, 10)
X, Y, Z = np.meshgrid(x, y, z)
U = -Y
V = X
W = np.zeros_like(Z)

fig, ax = vz.plot_3d_quiver(X, Y, Z, U, V, W, length=0.3, normalize=True)
vz.show()
```

#### `vz.plot_3d_stem(x, y, z, title=None, xlabel='X', ylabel='Y', zlabel='Z', **kwargs)`
3D stem plot (discrete points with stems to baseline).

```python
x = np.linspace(0, 10, 20)
y = np.sin(x)
z = np.cos(x)
fig, ax = vz.plot_3d_stem(x, y, z, linefmt='b-', markerfmt='bo')
vz.show()
```

#### `vz.plot_3d_bar(x, y, z, dx, dy, dz, title=None, **kwargs)`
3D bar chart.

```python
x = np.arange(5)
y = np.arange(5)
X, Y = np.meshgrid(x, y)
Z = np.random.rand(5, 5)
dx = dy = 0.8
dz = Z.flatten()
fig, ax = vz.plot_3d_bar(X.flatten(), Y.flatten(), np.zeros_like(Z.flatten()), dx, dy, dz)
vz.show()
```

#### `vz.plot_3d_voxels(voxels, title=None, **kwargs)`
3D voxel/volume rendering.

```python
# Create a sphere
voxels = np.zeros((20, 20, 20), dtype=bool)
x = y = z = np.linspace(-10, 10, 20)
X, Y, Z = np.meshgrid(x, y, z)
voxels[X**2 + Y**2 + Z**2 <= 100] = True
fig, ax = vz.plot_3d_voxels(voxels, edgecolor='k', facecolors='cyan')
vz.show()
```

#### `vz.figure3d(title=None, xlabel='X', ylabel='Y', zlabel='Z', figsize=(10, 8))`
Create an empty 3D figure for custom plotting. Returns `(fig, ax)`.

```python
fig, ax = vz.figure3d(title='Custom 3D Plot')
# Now use matplotlib's 3D API directly
ax.plot_surface(X, Y, Z, cmap='viridis')
ax.scatter(x_points, y_points, z_points, c='red')
ax.contour(X, Y, Z, levels=10, colors='black')
vz.show()
```

All 3D functions return `(fig, ax)` tuple and support full matplotlib customization via `**kwargs`.

### Style Management

#### `vz.set_style(style)`
Set global visual style.

```python
vz.set_style('default')    # Clean, modern default
vz.set_style('dark')       # Dark theme
vz.set_style('minimal')    # Minimal ink, maximum data
vz.set_style('publication')# Publication-ready
vz.set_style('seaborn')    # Seaborn-compatible
```

#### `vz.available_styles()`
List available style presets.

```python
print(vz.available_styles())
# ['default', 'dark', 'minimal', 'publication', 'seaborn']
```

#### `vz.create_custom_style(name, **kwargs)`
Create your own style.

```python
vz.create_custom_style('my_style',
    figure.figsize=(12, 8),
    axes.titlesize=16,
    axes.prop_cycle=plt.cycler('color', ['#FF0000', '#00FF00', '#0000FF'])
)
vz.set_style('my_style')
```

## Plot Types Supported

### Standard 2D Plots

| Plot Type | Use Case | Auto-detected When |
|-----------|----------|-------------------|
| `scatter` | Relationship between two numeric variables | Two numeric columns provided |
| `line` | Time series or sequential data | Datetime index or sorted x-axis |
| `bar` | Categorical comparisons | Categorical x with numeric y |
| `stacked_bar` | Part-to-whole comparisons across categories | Multiple y columns with `stacked=True` |
| `grouped_bar` | Side-by-side category comparisons | Multiple y columns with grouped layout |
| `hist` | Distribution of single variable | Single numeric column |
| `box` | Distribution with outliers | Box plot recommended |
| `violin` | Detailed distribution shape | Violin plot recommended |
| `kde` | Smooth density estimate | KDE recommended |
| `area` | Cumulative totals | Area plot specified |
| `heatmap` | Correlation matrix (with optional annotations) | Matrix data or 3+ numeric columns; supports `annot=True`, `fmt`, `annot_fontsize` |
| `pcolormesh` | Flexible colored grid cells (non-uniform grids) | Gridded x, y, z data |
| `contour` | 2D contour lines (topographic maps) | Gridded x, y, z data |
| `hexbin` | 2D density for large scatter (>50k points) | Large dataset auto-detected (>50k points) |
| `step` | Discrete changes, digital signals | Explicit `kind='step'` |
| `fill_between` | Confidence intervals, ranges | Requires y, optionally y_lower/y_upper |
| `quiver` | 2D vector field (arrows) | Requires x, y, u, v components |
| `spy` | Sparse matrix visualization | DataFrame or 2D array |
| `polar` | Radial/angular coordinates (cyclic data) | Requires theta and r |
| `table` | Render data as table figure | Explicit `kind='table'` |
| `eventplot` | Multiple event sequences/timelines | Multiple sequence columns |
| `waterfall` | Cumulative effect (bridge chart) | Requires x (category) and y (value) |
| `gantt` | Project/task timelines | Requires task, start, and end/duration |
| `ohlc_volume` | Financial OHLC with volume bars | Requires open, high, low, close, volume |
| `pie` | Proportional breakdown | Single categorical column with ≤6 unique values |
| `stem` | Discrete data points with stems | Stem plot specified |
| `errorbar` | Data with error margins | Error values provided |
| `candlestick` | Financial OHLC data | Open, high, low, close columns |
| `streamplot` | Vector field flow lines | Requires x, y, u, v grid components; handles flattened long-form data automatically |
| `tricontour` | Contour lines on scattered (unstructured) data | Requires x, y, z columns; triangulates automatically |
| `tricontourf` | Filled contours on scattered data | Requires x, y, z columns; triangulates automatically |

### Advanced Visualizations

| Plot Type | Use Case | Requirements |
|-----------|----------|--------------|
| `sankey` | Flow between stages/categories | Multi-stage path or source-target pairs; requires `networkx` |
| `sunburst` | Hierarchical radial layout | Hierarchical path with value; optional `squarify` |
| `treemap` | Hierarchical rectangular layout | Hierarchical path with value; requires `squarify` |
| `network` | Graph relationships | Edge list (source, target); requires `networkx` |

### Statistical & EDA Plots

| Plot Type | Use Case | Requirements |
|-----------|----------|--------------|
| `pairplot` | Scatter matrix with histograms/KDE on diagonal | Multiple numeric columns; optional `scipy` |
| `jointplot` | Scatter plot with marginal distributions | Two numeric columns; optional `scipy` |
| `boxen` | Letter-value box plot (enhanced box) | Categorical x, numeric y |
| `rug` | Marginal tick marks showing distribution | Single numeric column |
| `strip` | Categorical scatter with jitter | Categorical x, numeric y |
| `swarm` | Non-overlapping categorical scatter | Categorical x, numeric y |
| `qqplot` | Q-Q plot vs theoretical distribution | Single numeric column; requires `scipy` |
| `residualplot` | Residuals vs fitted for regression | Two numeric columns (x predictor, y response) |
| `autocorrelation` | Autocorrelation function (ACF) | Single time series column |
| `lagplot` | Scatter of series vs its lag | Single time series column |
| `andrews_curves` | Multivariate visualization by class | Multiple numeric columns + grouping column |
| `parallel_coordinates` | Multivariate lines on parallel axes | Multiple numeric columns + grouping column |
| `radviz` | Radial visualization for multivariate data | Multiple numeric columns + grouping column; optional `scipy` |

All these plots are also available via `vz.plot(df, kind='...')` with appropriate parameters.

**Example Usage:**

```python
import bottleviz as vz
import pandas as pd

# Pair plot (scatter matrix)
vz.plot(df, kind='pairplot', columns=['x1', 'x2', 'x3'])

# Joint plot with histogram margins
vz.plot(df, x='x', y='y', kind='jointplot')

# Boxen plot (letter-value boxes)
vz.plot(df, x='category', y='value', kind='boxen')

# QQ plot for normality check
vz.plot(df, x='residuals', kind='qqplot')

# Autocorrelation plot for time series
vz.plot(ts_df, x='value', kind='autocorrelation', lags=50)

# Andrews curves for multi-class data
vz.plot(iris, x='species', columns=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'], kind='andrews')
```

### 3D Visualizations

| Plot Type | Use Case | Data Format |
|-----------|----------|-------------|
| `plot_3d_surface` | Continuous surface (points connected as planes) | 2D meshgrid arrays (X, Y, Z) |
| `plot_3d_wireframe` | Wireframe mesh showing grid structure | 2D meshgrid arrays (X, Y, Z) |
| `plot_3d_trisurf` | Triangular surface for scattered data | 1D arrays (x, y, z) - triangulated automatically |
| `plot_3d_contour` | 3D contour lines | 2D meshgrid arrays (X, Y, Z) |
| `plot_3d_contourf` | Filled 3D contours | 2D meshgrid arrays (X, Y, Z) |
| `plot_3d_quiver` | 3D vector field (arrows) | Grid coordinates (X, Y, Z) and vector components (U, V, W) |
| `plot_3d_stem` | 3D stem plots | 1D arrays (x, y, z) |
| `plot_3d_bar` | 3D bar chart | Positions (x, y, z) and dimensions (dx, dy, dz) |
| `plot_3d_voxels` | 3D volume/cube rendering | 3D boolean or scalar array |
| `figure3d` | Create empty 3D figure for custom plotting | Returns (fig, ax) for manual plotting |

All 3D functions provide full access to matplotlib's 3D API via `**kwargs`.

### Geographic Plots

| Plot Type | Use Case | Requirements |
|-----------|----------|--------------|
| `choropleth` | Color regions by data values | Geometry column; requires `geopandas` |
| `scatter_geo` | Points on map from lat/lon | `lat` and `lon` columns; requires `geopandas`, `shapely` |
| `flow_map` | Flow lines between locations | Origin/destination coordinates; requires `geopandas`, `shapely` |
| `tile_map` | Choropleth with basemap tiles | Geometry column; requires `geopandas`, `contextily` |
| `cartogram` | Area-scaled cartogram | Geometry column and value; requires `geopandas` |

### Detailed Geographic Plot Examples

**Choropleth Maps**
```python
import bottleviz as vz
import geopandas as gpd
from shapely.geometry import Polygon

# Create GeoDataFrame with polygon geometries
polygons = [Polygon([(0,0), (1,0), (1,1), (0,1)]),
            Polygon([(1,0), (2,0), (2,1), (1,1)])]
gdf = gpd.GeoDataFrame({
    'region': ['A', 'B'],
    'population': [1000, 2000]
}, geometry=polygons, crs='EPSG:4326')

vz.plot(gdf, kind='choropleth', geometry='geometry', value='population',
        title='Population by Region', cmap='viridis')
```

**Scatter Geo**
```python
import bottleviz as vz
import pandas as pd

df = pd.DataFrame({
    'latitude': [40.7128, 34.0522, 41.8781],
    'longitude': [-74.0060, -118.2437, -87.6298],
    'city': ['New York', 'Los Angeles', 'Chicago'],
    'temperature': [22, 18, 15]
})

vz.plot(df, kind='scatter_geo', lat='latitude', lon='longitude',
        value='temperature', title='Temperature by City',
        cmap='plasma', markersize=100, alpha=0.7)
```

**Flow Maps**
```python
import bottleviz as vz

flow_data = pd.DataFrame({
    'origin_lat': [40.7128, 34.0522],
    'origin_lon': [-74.0060, -118.2437],
    'dest_lat': [40.7589, 34.0522],
    'dest_lon': [-73.9851, -118.2437],
    'volume': [1000, 500]
})

vz.plot(flow_data, kind='flow_map',
        origin_lat='origin_lat', origin_lon='origin_lon',
        dest_lat='dest_lat', dest_lon='dest_lon',
        flow='volume', title='Migration Flows', color='#2196F3')
```

**Tile Maps**
```python
import bottleviz as vz
import geopandas as gpd
import contextily as ctx

# Load or create GeoDataFrame
gdf = gpd.GeoDataFrame(...).to_crs(epsg=3857)  # Reproject to Web Mercator

vz.plot(gdf, kind='tile_map', value='density',
        tile_source=ctx.providers.OpenStreetMap.Mapnik)
```

**Cartograms**
```python
import bottleviz as vz
import geopandas as gpd
from shapely.geometry import Polygon

polygons = [Polygon([(0,0), (1,0), (1,1), (0,1)]),
            Polygon([(1,0), (2,0), (2,1), (1,1)])]
gdf = gpd.GeoDataFrame({
    'region': ['A', 'B'],
    'population': [1000, 4000]  # B will appear 4x larger
}, geometry=polygons)

vz.plot(gdf, kind='cartogram', geometry='geometry', value='population',
        title='Population Cartogram')
```

## Solving Gaps in Existing Libraries

### vs Matplotlib
- **Simplicity**: No more verbose `fig, ax = plt.subplots()` boilerplate
- **Smarter defaults**: Beautiful plots automatically
- **Type inference**: No need to specify plot type manually

### vs Seaborn
- **Performance**: Better optimization for large datasets
- **Consistency**: One function for all plot types
- **Flexibility**: Works with numpy arrays directly

### vs Plotly
- **Lightweight**: Pure Python core, no JavaScript needed
- **Static quality**: Publication-ready out of the box
- **Easier deployment**: No browser dependencies

## Advanced Features

### Large Dataset Optimization
```python
# Automatic downsampling for >10k points
vz.plot(huge_df)  # Smooth even with 1M rows
```

### Smart Color Palettes
```python
# Automatically colorblind-friendly
vz.plot(df, x='cat', y='val', kind='bar')  # Beautiful colors

# Custom palette
vz.plot(df, x='cat', y='val', kind='bar', palette='pastel')
```

### Automatic Subplot Layout
```python
# Automatically arranges subplots
vz.visualize(df, max_plots=6)  # Smart 2x3 layout
```

### Pandas/Polars Integration
```python
# Works with many data structures
vz.plot(df)                    # pandas DataFrame
vz.plot(pl.DataFrame(...))    # polars DataFrame
vz.plot(np_array)             # NumPy array
vz.plot([1,2,3,4,5])          # Python list
vz.plot({'x': [...], 'y': [...]})  # Dictionary
```

## Limitations and Future Work

**Current limitations:**
- Only matplotlib backend implemented (Plotly backend planned)
- Some advanced charts (Sankey, Sunburst, Treemap, Network) require optional dependencies (networkx, squarify)
- 3D visualizations use matplotlib's mplot3d (limited interactivity compared to Plotly)
- Polar plots use matplotlib's polar projection (basic features only)
- Pcolormesh and contour require gridded data format

**Planned features:**
- [ ] Plotly interactive backend with enhanced 3D
- [ ] Bokeh backend
- [ ] GPU acceleration with CuPy
- [ ] Animation support for time series
- [ ] Export to HTML with interactivity
- [ ] Graphviz layout for network graphs
- [ ] Faceted/trellised subplot grids

## Requirements

- Python >= 3.8
- NumPy >= 1.18.0
- Pandas >= 1.0.0
- Matplotlib >= 3.0.0

Optional:
- plotly >= 5.0.0 (for interactive plots)
- datashader >= 0.13.0 (for massive datasets)
- networkx (for network graphs and Sankey diagrams)
- squarify (for treemaps)
- polars (alternative to pandas)
- **geopandas >= 0.10.0, shapely >= 1.8.0, contextily >= 1.0.0** (for geographic visualizations)

Install all geographic dependencies: `pip install bottleviz[geo]`

### Interactive HTML Plots (Plotly Backend)

BottleViz includes an optional Plotly backend for creating interactive, web-based visualizations:

```python
import bottleviz as vz
import pandas as pd

df = pd.DataFrame({'x': [1,2,3], 'y': [4,5,6]})

# Create interactive HTML
html = vz.show_plotly(df, x='x', y='y', kind='scatter', title='My Plot')

# Save to file
vz.save_plotly(df, 'interactive.html', x='x', y='y', kind='scatter')

# Or display in Jupyter
from IPython.display import HTML
HTML(html)
```

Features:
- Interactive zoom, pan, hover tooltips
- 3D rotation (for 3D plots)
- Clickable legends
- Animation support
- Works in any modern web browser

**Requirements**: `pip install plotly`

**Demo**: See `examples/demo_plotly_interactive.py`

## Contributing

We welcome contributions! Please see our contributing guide in the repository.

## License

MIT License - see LICENSE file for details.

## Examples Gallery

More examples available in the `examples/` directory:

1. **Basic Plots**: Line, scatter, bar, histogram (`demo.py`, `example.py`)
2. **Statistical**: Box, violin, KDE
3. **Compositional**: Pie, area, stacked charts, grouped bar
4. **Multivariate**: Heatmap, pair plots, 3D, contour, pcolormesh
5. **Time Series**: Date handling, rolling windows, candlestick
6. **Large Data**: Downsampling, datashader, hexbin
7. **Styling**: Themes, custom palettes, publication tips
8. **Advanced**: Sankey, Sunburst, Treemap, Network, Candlestick
9. **New Plot Types (v0.2.0)**:
   - `stacked_bar` & `grouped_bar` - Categorical comparisons
   - `hexbin` - 2D density for large datasets
   - `step` - Discrete step plots
   - `fill_between` - Confidence intervals
   - `contour` - 2D contour lines
   - `pcolormesh` - Flexible grid coloring
   - `quiver` - 2D vector fields
   - `spy` - Sparse matrix visualization
   - `polar` - Radial/angular plots
   - `table` - Data as table figure
   - `eventplot` - Event sequences/timelines
   - `waterfall` - Waterfall/bridge charts (cumulative effects)
   - `gantt` - Gantt charts for project management
   - `ohlc_volume` - OHLC candlestick with volume bars
   - `streamplot` - Vector field flow lines
   - `tricontour` & `tricontourf` - Contours on scattered (unstructured) data
10. **Layout & Composition Utilities**:
    - `subplots()` - Create multi-subplot figures with shared axes
    - `inset()` - Create plots with zoomed inset axes
    - `figure()` - Simple figure creation shortcut
11. **Statistical & EDA Plots**:
    - `demo_statistical_plots.py` - Comprehensive demo of 13+ statistical plots (pairplot, jointplot, boxen, rug, strip, swarm, qqplot, residualplot, autocorrelation, lagplot, andrews_curves, parallel_coordinates, radviz)
12. **Interactive HTML Plots**:
    - `demo_plotly_interactive.py` - Create interactive Plotly visualizations with `show_plotly()` and `save_plotly()` functions
13. **3D Visualizations**:
    - `all_3d_plots.py` - Comprehensive demo of all 10+ 3D plot types (surface, wireframe, trisurf, contour, quiver, stem, bar3d, voxels)
    - `array_slices_3d.py` - Advanced 3D array slices with intersecting planes
    - `demo_show_close.py` - Cone surface plot with show/close functions
14. **Complete Plot Type Gallery**:
    - `demo_all_plot_types.py` - **NEW!** Comprehensive demonstration of ALL 40+ plot types (matplotlib PNG + plotly HTML outputs)

Run examples:
```bash
python -m bottleviz.examples
```

## Citation

If you use BottleViz in your research, please cite:

```bibtex
@software{bottleviz2024,
  author = {{Pavan Paari}},
  title = {{BottleViz: A Modern Python Visualization Library}},
  year = {2026},
  url = {https://github.com/DHS-IT-Solutions/BottleViz.git}
}
```

---

