diffusion-cartogram 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jonah Spector
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.4
2
+ Name: diffusion-cartogram
3
+ Version: 0.2.0
4
+ Summary: Volumetric Density-Equalizing Reference Map — 3D shape deformation and 2D cartogram generation
5
+ Author-email: Jonah Spector <spector.jo@northeastern.edu>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jspector792/diffusion-cartogram
8
+ Project-URL: Repository, https://github.com/jspector792/diffusion-cartogram
9
+ Project-URL: Issues, https://github.com/jspector792/diffusion-cartogram/issues
10
+ Keywords: cartogram,deformation,3d,2d,visualization,density-equalizing,vderm,geojson,shapefile
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Topic :: Scientific/Engineering :: Visualization
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: numpy>=1.20
24
+ Requires-Dist: scipy>=1.7
25
+ Requires-Dist: matplotlib>=3.3
26
+ Requires-Dist: pandas>=1.3
27
+ Requires-Dist: tqdm>=4.60
28
+ Provides-Extra: 2d
29
+ Requires-Dist: geopandas>=0.12; extra == "2d"
30
+ Requires-Dist: rasterio>=1.3; extra == "2d"
31
+ Requires-Dist: shapely>=2.0; extra == "2d"
32
+ Provides-Extra: 3d
33
+ Requires-Dist: pymeshlab>=2023.12; extra == "3d"
34
+ Provides-Extra: all
35
+ Requires-Dist: geopandas>=0.12; extra == "all"
36
+ Requires-Dist: rasterio>=1.3; extra == "all"
37
+ Requires-Dist: shapely>=2.0; extra == "all"
38
+ Requires-Dist: pymeshlab>=2023.12; extra == "all"
39
+ Dynamic: license-file
40
+
41
+ # diffusion-cartogram
42
+ [![PyPI version](https://badge.fury.io/py/diffusion-cartogram.svg)](https://badge.fury.io/py/diffusion-cartogram)
43
+ [![GitHub release](https://img.shields.io/github/v/release/jspector792/diffusion-cartogram)](https://github.com/jspector792/diffusion-cartogram/releases)
44
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
46
+
47
+ 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.
48
+
49
+ ## Overview
50
+
51
+ 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.
52
+
53
+ 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.
54
+
55
+ ### Applications
56
+
57
+ - 3D data visualization and cartograms
58
+ - 2D geographic cartograms from GeoJSON / Shapefiles
59
+ - Adaptive mesh refinement
60
+ - Shape modeling and morphing
61
+
62
+ ### Key Features
63
+
64
+ - **3D**: Fast regular grid interpolation, STL / VTK / XYZ export, optional PyMeshLab mesh support
65
+ - **2D (new)**: GeoJSON and Shapefile input, GeoTIFF built-in densities, 2D scatter / heatmap visualization
66
+ - Comprehensive matplotlib animations for both 2D and 3D pipelines
67
+ - Progress tracking with intermediate state exports
68
+ - Automatic grid sizing with customizable padding
69
+
70
+ ## Installation
71
+
72
+ ### Base / lite (no optional dependencies)
73
+ ```bash
74
+ pip install diffusion-cartogram
75
+ ```
76
+
77
+ ### With 2-D geographic I/O (GeoJSON, Shapefile, GeoTIFF)
78
+ ```bash
79
+ pip install diffusion-cartogram[2D]
80
+ ```
81
+
82
+ ### With 3-D mesh support (STL, OBJ, Poisson reconstruction)
83
+ ```bash
84
+ pip install diffusion-cartogram[3D]
85
+ ```
86
+
87
+ ### Full installation
88
+ ```bash
89
+ pip install diffusion-cartogram[all]
90
+ ```
91
+
92
+ ### Development
93
+ ```bash
94
+ git clone https://github.com/jspector792/diffusion-cartogram.git
95
+ cd diffusion-cartogram
96
+ pip install -e .[all]
97
+ ```
98
+
99
+ ## Quick Start — 3D
100
+
101
+ ```python
102
+ import diffusion_cartogram as vd
103
+ import numpy as np
104
+
105
+ # 1. Load a mesh and sample a surface point cloud
106
+ surface_points, normals = vd.create_pcd('mesh.stl', n_pts=25000)
107
+
108
+ # 2. Create computational grid (automatically sized)
109
+ params = vd.make_initial_grid(surface_points, max_points=32768)
110
+
111
+ # 3. Initialize VDERM grid and set density
112
+ grid = vd.VDERMGrid(params['shape'], params['h'], params['min_bounds'])
113
+
114
+ def my_density(x, y, z):
115
+ r = np.sqrt((x - 1.5)**2 + (y - 1.5)**2 + (z - 1.5)**2)
116
+ return 1.0 + 3.0 * np.exp(-5 * r**2)
117
+
118
+ grid.set_density(my_density)
119
+
120
+ # 4. Run deformation
121
+ result = vd.run_VDERM(grid, n_max=100, max_eps=0.02)
122
+
123
+ # 5. Apply deformation to surface and export
124
+ final_surface = vd.interpolate_to_surface(
125
+ surface_points, params, result.get_displacement_field()
126
+ )
127
+ vd.export_mesh_file('deformed_mesh.stl', final_surface)
128
+ ```
129
+
130
+ ## Quick Start — 2D Cartogram
131
+
132
+ ```python
133
+ import diffusion_cartogram as vd
134
+
135
+ # 1. Load geographic boundary (GeoJSON or Shapefile)
136
+ pts, crs = vd.read_geojson('countries.geojson') # or read_shapefile()
137
+
138
+ # 2. Create 2D grid sized to the data
139
+ params = vd.make_initial_grid_2d(pts, max_points=16384)
140
+ grid = vd.VDERMGrid2D(params['shape'], params['h'], params['min_bounds'])
141
+
142
+ # 3. Set density from a GeoTIFF (e.g. population raster)
143
+ vd.density_from_geotiff(grid, 'population.tif')
144
+ # or define analytically: grid.set_density(lambda x, y: ...)
145
+
146
+ # 4. Run deformation — run_VDERM works for both 2D and 3D grids
147
+ result = vd.run_VDERM(grid, n_max=200, max_eps=0.02)
148
+
149
+ # 5. Apply deformation to map points
150
+ deformed = vd.interpolate_to_map_2d(
151
+ pts, params, result.get_displacement_field()
152
+ )
153
+
154
+ # 6. Visualize
155
+ dens = vd.interpolate_densities_2d(pts, result)
156
+ vd.plot_map_before_after(pts, deformed, densities=dens,
157
+ title='Population Cartogram')
158
+ ```
159
+
160
+ ## Examples
161
+
162
+ Detailed Jupyter notebook examples are in the `examples/` directory:
163
+
164
+ - **01_quickStart.ipynb**: Basic 3-D workflow and concepts
165
+ - **02_boundaryConditions.ipynb**: Boundary condition effects
166
+ - **03_densityFields.ipynb**: Different density functions
167
+ - **04_tracking.ipynb**: Animations and intermediate exports
168
+ - **05_diffusion-cartogram_lite.ipynb**: 3-D point-cloud workflow without mesh dependencies
169
+ - **06_2D_quickStart.ipynb**: 2-D quick start — 2×2 grid from scratch (base install)
170
+ - **07_worldCartogram.ipynb**: World population cartogram from GeoJSON / Shapefile / GeoTIFF (`pip install diffusion-cartogram[2D]`)
171
+ - **08_2D_lite.ipynb**: 2-D lite mode — XY CSV files only (base install)
172
+
173
+ ## File Formats
174
+
175
+ ### 3D — XYZ (space-delimited text)
176
+ ```
177
+ # 3 cols: positions only
178
+ x y z
179
+ # 4 cols: positions + density
180
+ x y z rho
181
+ # 6 cols: positions + normals / velocities
182
+ x y z n_x n_y n_z
183
+ # 7 cols: complete
184
+ x y z n_x n_y n_z rho
185
+ ```
186
+
187
+ ### 2D — CSV (space-delimited text)
188
+ ```
189
+ # 2 cols: positions only
190
+ x y
191
+ # 3 cols: positions + density
192
+ x y rho
193
+ ```
194
+
195
+ Geographic inputs: **GeoJSON**, **Shapefile** (via geopandas), **GeoTIFF** density rasters (via rasterio).
196
+
197
+ ## Tips
198
+
199
+ ### Grid Resolution
200
+ - **Quick test / 2D**: 4 000–16 000 points (64²–128²)
201
+ - **Standard 3D**: 30 000–50 000 points (30–35³)
202
+ - **High quality 3D**: 100 000–250 000 points (45–60³)
203
+
204
+ ### Density Field Design
205
+ - Keep densities positive: ρ > 0
206
+ - Avoid sharp discontinuities near object boundaries
207
+ - Embed large gradients in a uniform density sea rather than against a wall
208
+
209
+ ### Numerical Stability
210
+ If epsilon becomes very large or negative, reduce the timestep:
211
+ ```python
212
+ vd.run_VDERM(grid, dt=0.001)
213
+ ```
214
+
215
+ ## Known issues
216
+
217
+ ### macOS + conda: OpenMP conflict with pymeshlab (3D only)
218
+
219
+ Users running the 3D reconstruction features (`export_mesh_file`, `export_mesh_vtk`)
220
+ on macOS in a conda environment may encounter a hard crash:
221
+ ```
222
+ OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already initialized.
223
+ ```
224
+ This is caused by a conflict between the OpenMP runtime bundled inside pymeshlab's
225
+ wheel and the one loaded by conda-forge's numpy/scipy. It is not specific to
226
+ diffusion-cartogram — it will occur with any package that uses both pymeshlab and
227
+ conda-forge numpy on macOS.
228
+
229
+ **Fix:** Replace pymeshlab's bundled `libomp.dylib` with a symlink to conda's. Both
230
+ are LLVM OpenMP with the same ABI, so this is safe. The file to replace is at
231
+ `$CONDA_PREFIX/lib/python*/site-packages/pymeshlab/Frameworks/libomp.dylib`.
232
+ See [this discussion](https://stackoverflow.com/questions/53014306/error-15-initializing-libiomp5-dylib-but-found-libiomp5-dylib-already-initial) for
233
+ approaches and context. Note that the fix is environment-level and will need to be
234
+ reapplied if pymeshlab is reinstalled or upgraded.
235
+
236
+ ## Dependencies
237
+
238
+ | Dependency | Required for |
239
+ |---|---|
240
+ | numpy, scipy, matplotlib, tqdm | Always required |
241
+ | geopandas, rasterio, shapely | 2-D geographic I/O (`pip install diffusion-cartogram[2D]`) |
242
+ | pymeshlab | 3-D mesh I/O and reconstruction (`pip install diffusion-cartogram[3D]`) |
243
+
244
+ ## Citation
245
+
246
+ If you use this package in academic work, please cite the appropriate original paper(s):
247
+ ```bibtex
248
+ @article{choi2021volumetric,
249
+ title={Volumetric density-equalizing reference map with applications},
250
+ author={Choi, Gary Pui-Tung and Rycroft, Chris H},
251
+ journal={Journal of Scientific Computing},
252
+ volume={86},
253
+ number={3},
254
+ pages={1--26},
255
+ year={2021},
256
+ publisher={Springer}
257
+ }
258
+
259
+ @article{gastner2004,
260
+ title = {Diffusion-based method for producing density-equalizing maps},
261
+ author = {Gastner, Michael T. and Newman, M. E. J.},
262
+ journal = {Proceedings of the National Academy of Sciences},
263
+ volume = {101},
264
+ number = {20},
265
+ pages = {7499--7504},
266
+ year = {2004},
267
+ doi = {10.1073/pnas.0400280101}
268
+ }
269
+ ```
270
+ And optionally, this implementation:
271
+ ```bibtex
272
+ @software{vderm2026,
273
+ title={diffusion-cartogram: A Python implementation of Volumetric Density-Equalizing Reference Map},
274
+ author={Jonah Spector},
275
+ year={2026},
276
+ url={https://github.com/jspector792/diffusion-cartogram}
277
+ }
278
+ ```
279
+
280
+ ## License
281
+
282
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
283
+
284
+ ## Acknowledgments
285
+
286
+ - Original VDERM algorithm by Gary P.T. Choi and Chris H. Rycroft
287
+ - Based on the diffusion cartogram method by Gastner & Newman (2004)
@@ -0,0 +1,270 @@
1
+ # diffusion-cartogram
2
+ [![PyPI version](https://badge.fury.io/py/diffusion-cartogram.svg)](https://badge.fury.io/py/diffusion-cartogram)
3
+ [![GitHub release](https://img.shields.io/github/v/release/jspector792/diffusion-cartogram)](https://github.com/jspector792/diffusion-cartogram/releases)
4
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Volumetric 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.
8
+
9
+ <table>
10
+ <tr>
11
+ <td align="center"><b>3-D shape deformation (cube)</b></td>
12
+ <td align="center"><b>2-D cartogram (2×2 grid)</b></td>
13
+ </tr>
14
+ <tr>
15
+ <td><img src="examples/cube.gif"/></td>
16
+ <td><img src="examples/square.gif"/></td>
17
+ </tr>
18
+ </table>
19
+
20
+ ## Overview
21
+
22
+ 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.
23
+
24
+ v2.0 extends this to **2D** using the same diffusion-advection process — just one spatial dimension removed — making 2D cartograms straightforward to produce from standard geographic files (GeoJSON, Shapefile, GeoTIFF).
25
+
26
+ ### Applications
27
+
28
+ - 3D data visualization and cartograms
29
+ - **2D geographic cartograms** from GeoJSON / Shapefiles (new in v2.0)
30
+ - Adaptive mesh refinement
31
+ - Shape modeling and morphing
32
+
33
+ ### Key Features
34
+
35
+ - **3D**: Fast regular grid interpolation, XYZ / STL / VTK export, optional PyMeshLab mesh support
36
+ - **2D (new)**: GeoJSON and Shapefile input, GeoTIFF built-in densities, 2D heatmap / scatter visualization
37
+ - Comprehensive matplotlib animations for both pipelines
38
+ - Progress tracking with intermediate state exports
39
+ - Automatic grid sizing with customizable padding
40
+
41
+ ## Installation
42
+
43
+ ### Base / lite (no optional dependencies)
44
+ ```bash
45
+ pip install diffusion-cartogram
46
+ ```
47
+
48
+ ### With 2-D geographic I/O (GeoJSON, Shapefile, GeoTIFF)
49
+ ```bash
50
+ pip install diffusion-cartogram[2D]
51
+ ```
52
+
53
+ ### With 3-D mesh support (STL, OBJ, Poisson reconstruction)
54
+ ```bash
55
+ pip install diffusion-cartogram[3D]
56
+ ```
57
+
58
+ ### Full installation
59
+ ```bash
60
+ pip install diffusion-cartogram[all]
61
+ ```
62
+
63
+ ### Development
64
+ ```bash
65
+ git clone https://github.com/jspector792/diffusion-cartogram.git
66
+ cd diffusion-cartogram
67
+ pip install -e .[all]
68
+ ```
69
+
70
+ ## Quick Start — 3D
71
+
72
+ ```python
73
+ import diffusion_cartogram as vd
74
+ import numpy as np
75
+
76
+ surface_points, normals = vd.create_pcd('mesh.stl', n_pts=25000)
77
+ params = vd.make_initial_grid(surface_points, max_points=32768)
78
+ grid = vd.VDERMGrid(params['shape'], params['h'], params['min_bounds'])
79
+
80
+ def my_density(x, y, z):
81
+ r = np.sqrt((x - 1.5)**2 + (y - 1.5)**2 + (z - 1.5)**2)
82
+ return 1.0 + 3.0 * np.exp(-5 * r**2)
83
+
84
+ grid.set_density(my_density)
85
+ result = vd.run_VDERM(grid, n_max=100, max_eps=0.02)
86
+
87
+ final_surface = vd.interpolate_to_surface(
88
+ surface_points, params, result.get_displacement_field()
89
+ )
90
+ vd.export_mesh_file('deformed_mesh.stl', final_surface)
91
+ ```
92
+
93
+ ## Quick Start — 2D Cartogram
94
+
95
+ ```python
96
+ import diffusion_cartogram as vd
97
+
98
+ # Load geographic boundary (GeoJSON or Shapefile)
99
+ pts, crs = vd.read_geojson('countries.geojson')
100
+
101
+ # Create grid and set density from a GeoTIFF
102
+ params = vd.make_initial_grid_2d(pts, max_points=16384)
103
+ grid = vd.VDERMGrid2D(params['shape'], params['h'], params['min_bounds'])
104
+ vd.density_from_geotiff(grid, 'population.tif')
105
+
106
+ # run_VDERM works for both 2D and 3D grids
107
+ result = vd.run_VDERM(grid, n_max=200, max_eps=0.02)
108
+
109
+ deformed = vd.interpolate_to_map_2d(
110
+ pts, params, result.get_displacement_field()
111
+ )
112
+ dens = vd.interpolate_densities_2d(pts, result)
113
+ vd.plot_map_before_after(pts, deformed, densities=dens,
114
+ title='Population Cartogram')
115
+ ```
116
+
117
+ ## Examples
118
+
119
+ Detailed Jupyter notebook examples are available in the `examples/` directory:
120
+
121
+ - **01_quickStart.ipynb**: Basic 3-D workflow and concepts
122
+ - **02_boundaryConditions.ipynb**: Understanding and using boundary conditions
123
+ - **03_densityFields.ipynb**: Different density functions and their effects
124
+ - **04_tracking.ipynb**: Creating animations and tracking a 3-D deformation
125
+ - **05_diffusion-cartogram_lite.ipynb**: 3-D point-cloud workflow without mesh dependencies
126
+ - **06_2D_quickStart.ipynb**: 2-D quick start — 2×2 grid from scratch (base install)
127
+ - **07_worldCartogram.ipynb**: World population cartogram from GeoJSON / Shapefile / GeoTIFF (`pip install diffusion-cartogram[2D]`)
128
+ - **08_2D_lite.ipynb**: 2-D lite mode — XY CSV files only (base install)
129
+
130
+ ## File Formats
131
+
132
+ ### 3D — XYZ (space-delimited text)
133
+
134
+ ```
135
+ x y z # positions only
136
+ x y z rho # + density
137
+ x y z nx ny nz # + normals / velocities
138
+ x y z nx ny nz rho # complete
139
+ ```
140
+
141
+ `read_xyz()` and `write_xyz()` detect and handle all variants automatically.
142
+
143
+ ### 2D — CSV (space-delimited text)
144
+
145
+ ```
146
+ x y # positions only
147
+ x y rho # + density
148
+ ```
149
+
150
+ `read_csv_2d()` and `write_csv_2d()` handle both variants.
151
+ Geographic inputs: **GeoJSON** and **Shapefile** (via geopandas), **GeoTIFF** density rasters (via rasterio).
152
+
153
+ ## Tips and Best Practices
154
+
155
+ ### Choosing Grid Resolution
156
+
157
+ **3D:**
158
+ - Quick test: 15,000–30,000 points (20–30³)
159
+ - Standard: 30,000–50,000 points (30–35³)
160
+ - High quality: 100,000–250,000 points (45–60³)
161
+
162
+ **2D:**
163
+ - Quick test / small regions: 1,000–4,000 points (32²–64²)
164
+ - Standard cartogram: 4,000–16,000 points (64²–128²)
165
+ - High quality: 16,000–65,000 points (128²–256²)
166
+
167
+ Higher resolution gives smoother results but increases computation time.
168
+
169
+ ### Density Field Design
170
+
171
+ For smooth, predictable deformations:
172
+ - Keep densities positive: ρ > 0
173
+ - Keep sharp discontinuities 2-3 grid cells away from surface of the object
174
+ - When possible, keep large density gradients embedded in a uniform density sea, rather than against a fixed boundary
175
+
176
+ ### Boundary Conditions
177
+
178
+ The algorithm uses no-flux boundary conditions via ghost nodes:
179
+ - Density doesn't leak through boundaries
180
+ - Boundaries can still move slightly (typically << 1 grid cell)
181
+ - Use padding to minimize boundary effects unless a fixed boundary is needed
182
+
183
+ ### Numerical Stability
184
+
185
+ If you encounter instability (epsilon becoming very large or negative):
186
+
187
+ 1. Try smaller timestep: `vd.run_VDERM(grid, dt=0.001)`
188
+ 2. Check your density field for extreme gradients
189
+ 3. Increase grid resolution
190
+
191
+ For most cases, automatic timestep selection works well.
192
+
193
+ ## Known issues
194
+
195
+ ### macOS + conda: OpenMP conflict with pymeshlab (3D only)
196
+
197
+ Users running the 3D reconstruction features (`export_mesh_file`, `export_mesh_vtk`)
198
+ on macOS in a conda environment may encounter a hard crash:
199
+ ```
200
+ OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already initialized.
201
+ ```
202
+ This is caused by a conflict between the OpenMP runtime bundled inside pymeshlab's
203
+ wheel and the one loaded by conda-forge's numpy/scipy. It is not specific to
204
+ diffusion-cartogram — it will occur with any package that uses both pymeshlab and
205
+ conda-forge numpy on macOS.
206
+
207
+ **Fix:** Replace pymeshlab's bundled `libomp.dylib` with a symlink to conda's. Both
208
+ are LLVM OpenMP with the same ABI, so this is safe. The file to replace is at
209
+ `$CONDA_PREFIX/lib/python*/site-packages/pymeshlab/Frameworks/libomp.dylib`.
210
+ See [this discussion](https://stackoverflow.com/questions/53014306/error-15-initializing-libiomp5-dylib-but-found-libiomp5-dylib-already-initial) for
211
+ approaches and context. Note that the fix is environment-level and will need to be
212
+ reapplied if pymeshlab is reinstalled or upgraded.
213
+
214
+ ## Dependencies
215
+
216
+ ### Required
217
+ - numpy >= 1.20
218
+ - scipy >= 1.7
219
+ - matplotlib >= 3.3
220
+ - pandas >= 1.3
221
+ - tqdm >= 4.60
222
+
223
+ ### Optional
224
+ - pymeshlab >= 2023.12 — 3-D mesh I/O and Poisson reconstruction (`pip install diffusion-cartogram[3D]`)
225
+ - geopandas >= 0.12, rasterio >= 1.3, shapely >= 2.0 — 2-D geographic I/O (`pip install diffusion-cartogram[2D]`)
226
+
227
+ ## Citation
228
+
229
+ If you use this package in academic work, please cite the appropriate original paper(s):
230
+ ```bibtex
231
+ @article{choi2021volumetric,
232
+ title={Volumetric density-equalizing reference map with applications},
233
+ author={Choi, Gary Pui-Tung and Rycroft, Chris H},
234
+ journal={Journal of Scientific Computing},
235
+ volume={86},
236
+ number={3},
237
+ pages={1--26},
238
+ year={2021},
239
+ publisher={Springer}
240
+ }
241
+
242
+ @article{gastner2004,
243
+ title = {Diffusion-based method for producing density-equalizing maps},
244
+ author = {Gastner, Michael T. and Newman, M. E. J.},
245
+ journal = {Proceedings of the National Academy of Sciences},
246
+ volume = {101},
247
+ number = {20},
248
+ pages = {7499--7504},
249
+ year = {2004},
250
+ doi = {10.1073/pnas.0400280101}
251
+ }
252
+ ```
253
+ And optionally, this implementation:
254
+ ```bibtex
255
+ @software{vderm2026,
256
+ title={diffusion-cartogram: A Python implementation of Volumetric Density-Equalizing Reference Map},
257
+ author={Jonah Spector},
258
+ year={2026},
259
+ url={https://github.com/jspector792/diffusion-cartogram}
260
+ }
261
+ ```
262
+
263
+ ## License
264
+
265
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
266
+
267
+ ## Acknowledgments
268
+
269
+ - Original VDERM algorithm by Gary P.T. Choi and Chris H. Rycroft
270
+ - Based on the diffusion cartogram method by Gastner & Newman (2004)