Metadata-Version: 2.1
Name: diffusion-cartogram
Version: 0.2.1
Summary: Volumetric Density-Equalizing Reference Map — 3D shape deformation and 2D cartogram generation
Author-email: Jonah Spector <spector.jo@northeastern.edu>
License: MIT License
        
        Copyright (c) 2026 Jonah Spector
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Project-URL: Homepage, https://github.com/jspector792/diffusion-cartogram
Project-URL: Repository, https://github.com/jspector792/diffusion-cartogram
Project-URL: Issues, https://github.com/jspector792/diffusion-cartogram/issues
Keywords: cartogram,deformation,3d,2d,visualization,density-equalizing,vderm,geojson,shapefile
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Visualization
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
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Requires-Dist: matplotlib>=3.3
Requires-Dist: pandas>=1.3
Requires-Dist: tqdm>=4.60
Provides-Extra: 2d
Requires-Dist: geopandas>=0.12; extra == "2d"
Requires-Dist: rasterio>=1.3; extra == "2d"
Requires-Dist: shapely>=2.0; extra == "2d"
Provides-Extra: 3d
Requires-Dist: pymeshlab>=2023.12; extra == "3d"
Provides-Extra: all
Requires-Dist: geopandas>=0.12; extra == "all"
Requires-Dist: rasterio>=1.3; extra == "all"
Requires-Dist: shapely>=2.0; extra == "all"
Requires-Dist: pymeshlab>=2023.12; extra == "all"

# diffusion-cartogram 
[![PyPI version](https://badge.fury.io/py/diffusion-cartogram.svg)](https://badge.fury.io/py/diffusion-cartogram)
[![GitHub release](https://img.shields.io/github/v/release/jspector792/diffusion-cartogram)](https://github.com/jspector792/diffusion-cartogram/releases)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Density-Equalizing Reference Map — a Python implementation of the VDERM algorithm for **3D shape deformation** and (new in v2.0) **2D cartogram generation** from GeoJSON / Shapefile inputs.

## Overview

diffusion-cartogram implements the Volumetric Density-Equalizing Reference Map (VDERM) method by [Choi & Rycroft (2020)](https://link.springer.com/article/10.1007/s10915-021-01411-4). VDERM is a 3D generalization of the diffusion-based cartogram method, enabling volume-preserving deformations of 3D objects based on prescribed density distributions.

v2.0 extends this to **2D** using the same diffusion-advection process — no FFTs, just the VDERM physics with one spatial dimension removed — making 2D cartograms straightforward to produce from standard geographic files.

### Applications

- 3D data visualization and cartograms
- 2D geographic cartograms from GeoJSON / Shapefiles
- Adaptive mesh refinement
- Shape modeling and morphing

### Key Features

- **3D**: Fast regular grid interpolation, STL / VTK / XYZ export, optional PyMeshLab mesh support
- **2D (new)**: GeoJSON and Shapefile input, GeoTIFF built-in densities, 2D scatter / heatmap visualization
- Comprehensive matplotlib animations for both 2D and 3D pipelines
- Progress tracking with intermediate state exports
- Automatic grid sizing with customizable padding

## Installation

### Base / lite (no optional dependencies)
```bash
pip install diffusion-cartogram
```

### With 2-D geographic I/O (GeoJSON, Shapefile, GeoTIFF)
```bash
pip install diffusion-cartogram[2D]
```

### With 3-D mesh support (STL, OBJ, Poisson reconstruction)
```bash
pip install diffusion-cartogram[3D]
```

### Full installation
```bash
pip install diffusion-cartogram[all]
```

### Development
```bash
git clone https://github.com/jspector792/diffusion-cartogram.git
cd diffusion-cartogram
pip install -e .[all]
```

## Quick Start — 3D

```python
import diffusion_cartogram as vd
import numpy as np

# 1. Load a mesh and sample a surface point cloud
surface_points, normals = vd.create_pcd('mesh.stl', n_pts=25000)

# 2. Create computational grid (automatically sized)
params = vd.make_initial_grid(surface_points, max_points=32768)

# 3. Initialize VDERM grid and set density
grid = vd.VDERMGrid(params['shape'], params['h'], params['min_bounds'])

def my_density(x, y, z):
    r = np.sqrt((x - 1.5)**2 + (y - 1.5)**2 + (z - 1.5)**2)
    return 1.0 + 3.0 * np.exp(-5 * r**2)

grid.set_density(my_density)

# 4. Run deformation
result = vd.run_VDERM(grid, n_max=100, max_eps=0.02)

# 5. Apply deformation to surface and export
final_surface = vd.interpolate_to_surface(
    surface_points, params, result.get_displacement_field()
)
vd.export_mesh_file('deformed_mesh.stl', final_surface)
```

## Quick Start — 2D Cartogram

```python
import diffusion_cartogram as vd

# 1. Load geographic boundary (GeoJSON or Shapefile)
pts, crs = vd.read_geojson('countries.geojson')   # or read_shapefile()

# 2. Create 2D grid sized to the data
params = vd.make_initial_grid_2d(pts, max_points=16384)
grid = vd.VDERMGrid2D(params['shape'], params['h'], params['min_bounds'])

# 3. Set density from a GeoTIFF (e.g. population raster)
vd.density_from_geotiff(grid, 'population.tif')
# or define analytically:  grid.set_density(lambda x, y: ...)

# 4. Run deformation — run_VDERM works for both 2D and 3D grids
result = vd.run_VDERM(grid, n_max=200, max_eps=0.02)

# 5. Apply deformation to map points
deformed = vd.interpolate_to_map_2d(
    pts, params, result.get_displacement_field()
)

# 6. Visualize
dens = vd.interpolate_densities_2d(pts, result)
vd.plot_map_before_after(pts, deformed, densities=dens,
                         title='Population Cartogram')
```

## Examples

Detailed Jupyter notebook examples are in the `examples/` directory:

- **01_quickStart.ipynb**: Basic 3-D workflow and concepts
- **02_boundaryConditions.ipynb**: Boundary condition effects
- **03_densityFields.ipynb**: Different density functions
- **04_tracking.ipynb**: Animations and intermediate exports
- **05_diffusion-cartogram_lite.ipynb**: 3-D point-cloud workflow without mesh dependencies
- **06_2D_quickStart.ipynb**: 2-D quick start — 2×2 grid from scratch (base install)
- **07_worldCartogram.ipynb**: World population cartogram from GeoJSON / Shapefile / GeoTIFF (`pip install diffusion-cartogram[2D]`)
- **08_2D_lite.ipynb**: 2-D lite mode — XY CSV files only (base install)

## File Formats

### 3D — XYZ (space-delimited text)
```
# 3 cols: positions only
x y z
# 4 cols: positions + density
x y z rho
# 6 cols: positions + normals / velocities
x y z n_x n_y n_z
# 7 cols: complete
x y z n_x n_y n_z rho
```

### 2D — CSV (space-delimited text)
```
# 2 cols: positions only
x y
# 3 cols: positions + density
x y rho
```

Geographic inputs: **GeoJSON**, **Shapefile** (via geopandas), **GeoTIFF** density rasters (via rasterio).

## Tips

### Grid Resolution
- **Quick test / 2D**: 4 000–16 000 points (64²–128²)
- **Standard 3D**: 30 000–50 000 points (30–35³)
- **High quality 3D**: 100 000–250 000 points (45–60³)

### Density Field Design
- Keep densities positive: ρ > 0
- Avoid sharp discontinuities near object boundaries
- Embed large gradients in a uniform density sea rather than against a wall

### Numerical Stability
If epsilon becomes very large or negative, reduce the timestep:
```python
vd.run_VDERM(grid, dt=0.001)
```

## Known issues

### macOS + conda: OpenMP conflict with pymeshlab (3D only)

Users running the 3D reconstruction features (`export_mesh_file`, `export_mesh_vtk`) 
on macOS in a conda environment may encounter a hard crash:
```
OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already initialized.
```
This is caused by a conflict between the OpenMP runtime bundled inside pymeshlab's 
wheel and the one loaded by conda-forge's numpy/scipy. It is not specific to 
diffusion-cartogram — it will occur with any package that uses both pymeshlab and 
conda-forge numpy on macOS.

**Fix:** Replace pymeshlab's bundled `libomp.dylib` with a symlink to conda's. Both 
are LLVM OpenMP with the same ABI, so this is safe. The file to replace is at 
`$CONDA_PREFIX/lib/python*/site-packages/pymeshlab/Frameworks/libomp.dylib`. 
See [this discussion](https://stackoverflow.com/questions/53014306/error-15-initializing-libiomp5-dylib-but-found-libiomp5-dylib-already-initial) for 
approaches and context. Note that the fix is environment-level and will need to be 
reapplied if pymeshlab is reinstalled or upgraded.

## Dependencies

| Dependency | Required for |
|---|---|
| numpy, scipy, matplotlib, tqdm | Always required |
| geopandas, rasterio, shapely | 2-D geographic I/O (`pip install diffusion-cartogram[2D]`) |
| pymeshlab | 3-D mesh I/O and reconstruction (`pip install diffusion-cartogram[3D]`) |

## Citation

If you use this package in academic work, please cite the appropriate original paper(s):
```bibtex
@article{choi2021volumetric,
  title={Volumetric density-equalizing reference map with applications},
  author={Choi, Gary Pui-Tung and Rycroft, Chris H},
  journal={Journal of Scientific Computing},
  volume={86},
  number={3},
  pages={1--26},
  year={2021},
  publisher={Springer}
}

@article{gastner2004,
  title   = {Diffusion-based method for producing density-equalizing maps},
  author  = {Gastner, Michael T. and Newman, M. E. J.},
  journal = {Proceedings of the National Academy of Sciences},
  volume  = {101},
  number  = {20},
  pages   = {7499--7504},
  year    = {2004},
  doi     = {10.1073/pnas.0400280101}
}
```
And optionally, this implementation:
```bibtex
@software{vderm2026,
  title={diffusion-cartogram: A Python implementation of Volumetric Density-Equalizing Reference Map},
  author={Jonah Spector},
  year={2026},
  url={https://github.com/jspector792/diffusion-cartogram}
}
```

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Acknowledgments

- Original VDERM algorithm by Gary P.T. Choi and Chris H. Rycroft
- Based on the diffusion cartogram method by Gastner & Newman (2004)
