cajal 1.0.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.
- cajal-1.0.0/LICENSE.md +21 -0
- cajal-1.0.0/PKG-INFO +112 -0
- cajal-1.0.0/README.md +48 -0
- cajal-1.0.0/pyproject.toml +91 -0
- cajal-1.0.0/setup.cfg +8 -0
- cajal-1.0.0/setup.py +14 -0
- cajal-1.0.0/src/cajal/EMD.h +38 -0
- cajal-1.0.0/src/cajal/EMD_wrapper.cpp +220 -0
- cajal-1.0.0/src/cajal/__init__.py +0 -0
- cajal-1.0.0/src/cajal/combined_slb_qgw.py +588 -0
- cajal-1.0.0/src/cajal/deformation_vis.py +196 -0
- cajal-1.0.0/src/cajal/gw_cython.cpp +39294 -0
- cajal-1.0.0/src/cajal/laplacian_score.py +435 -0
- cajal-1.0.0/src/cajal/partial.py +220 -0
- cajal-1.0.0/src/cajal/qgw.py +569 -0
- cajal-1.0.0/src/cajal/run_gw.py +478 -0
- cajal-1.0.0/src/cajal/sample_mesh.py +426 -0
- cajal-1.0.0/src/cajal/sample_seg.py +175 -0
- cajal-1.0.0/src/cajal/sample_swc.py +584 -0
- cajal-1.0.0/src/cajal/slb.cpp +13732 -0
- cajal-1.0.0/src/cajal/swc.py +918 -0
- cajal-1.0.0/src/cajal/ternary.py +284 -0
- cajal-1.0.0/src/cajal/utilities.py +471 -0
- cajal-1.0.0/src/cajal/weighted_tree.py +110 -0
- cajal-1.0.0/src/cajal/wnn.py +196 -0
- cajal-1.0.0/src/cajal.egg-info/PKG-INFO +112 -0
- cajal-1.0.0/src/cajal.egg-info/SOURCES.txt +40 -0
- cajal-1.0.0/src/cajal.egg-info/dependency_links.txt +1 -0
- cajal-1.0.0/src/cajal.egg-info/requires.txt +28 -0
- cajal-1.0.0/src/cajal.egg-info/top_level.txt +1 -0
- cajal-1.0.0/tests/test_laplacian_score.py +103 -0
- cajal-1.0.0/tests/test_qgw.py +25 -0
- cajal-1.0.0/tests/test_run_gw.py +22 -0
- cajal-1.0.0/tests/test_sample_mesh.py +23 -0
- cajal-1.0.0/tests/test_sample_seg.py +17 -0
- cajal-1.0.0/tests/test_sample_swc.py +52 -0
- cajal-1.0.0/tests/test_swc.py +192 -0
- cajal-1.0.0/tests/test_ternary.py +17 -0
- cajal-1.0.0/tests/test_utilities.py +36 -0
cajal-1.0.0/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 CAJAL authors
|
|
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.
|
cajal-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cajal
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A library for multi-modal cell morphology analyses using Gromov-Wasserstein (GW) distance.
|
|
5
|
+
Author-email: Pablo Cámara <pcamara@pennmedicine.upenn.edu>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2022 CAJAL authors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: git-repo, https://github.com/CamaraLab/CAJAL
|
|
29
|
+
Project-URL: readthedocs, https://cajal.readthedocs.io/en/latest/
|
|
30
|
+
Project-URL: biorxiv, https://www.biorxiv.org/content/10.1101/2022.05.19.492525v2
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Framework :: Jupyter
|
|
34
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
35
|
+
Requires-Python: >=3.9
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
License-File: LICENSE.md
|
|
38
|
+
Requires-Dist: igraph
|
|
39
|
+
Requires-Dist: leidenalg
|
|
40
|
+
Requires-Dist: networkx>=2.8.8
|
|
41
|
+
Requires-Dist: numpy
|
|
42
|
+
Requires-Dist: cython>=3
|
|
43
|
+
Requires-Dist: pathos
|
|
44
|
+
Requires-Dist: tqdm>=4.64.1
|
|
45
|
+
Requires-Dist: potpourri3d
|
|
46
|
+
Requires-Dist: pynndescent>=0.5.13
|
|
47
|
+
Requires-Dist: python-louvain
|
|
48
|
+
Requires-Dist: scipy>=1.10
|
|
49
|
+
Requires-Dist: scikit-image
|
|
50
|
+
Requires-Dist: tifffile
|
|
51
|
+
Requires-Dist: trimesh
|
|
52
|
+
Requires-Dist: umap-learn>=0.5.3
|
|
53
|
+
Requires-Dist: mpltern>=1.0.0
|
|
54
|
+
Requires-Dist: scikit-dimension
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Requires-Dist: mypy>=0.991; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest>=7.2.1; extra == "dev"
|
|
58
|
+
Requires-Dist: pre-commit>=2.20.0; extra == "dev"
|
|
59
|
+
Provides-Extra: vis
|
|
60
|
+
Requires-Dist: matplotlib>=3.7.0; extra == "vis"
|
|
61
|
+
Requires-Dist: networkx; extra == "vis"
|
|
62
|
+
Requires-Dist: navis; extra == "vis"
|
|
63
|
+
Requires-Dist: mpltern; extra == "vis"
|
|
64
|
+
|
|
65
|
+
# CAJAL <a href='https://github.com/CamaraLab/CAJAL'><img src="docs/images/logo.png" align="right" width="24%"/></a>
|
|
66
|
+
[](https://github.com/CamaraLab/CAJAL/actions/workflows/python-package.yml)
|
|
67
|
+
[](https://codecov.io/github/CamaraLab/CAJAL)
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
CAJAL is a Python library for multi-modal cell morphology analyses using Gromov-Wasserstein (GW) distance. Detailed information about the methods implemented in CAJAL can be found in:
|
|
71
|
+
|
|
72
|
+
K. W. Govek, P. Nicodemus, Y. Lin, J. Crawford, A. B. Saturnino, H. Cui, K. Zoga, M. P. Hart, P. G. Camara, _CAJAL enables analysis and integration of single-cell morphological data using metric geometry_. **Nature Communications** 14 (2023) 3672. [DOI:10.1038/s41467-023-39424-2](https://doi.org/10.1038/s41467-023-39424-2)
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
Until we upload the package to PyPI, the pip installation works from GitHub:
|
|
76
|
+
```commandline
|
|
77
|
+
pip install git+https://github.com/CamaraLab/CAJAL.git
|
|
78
|
+
```
|
|
79
|
+
Installation on a standard desktop computer should take a few minutes.
|
|
80
|
+
|
|
81
|
+
----
|
|
82
|
+
|
|
83
|
+
A C++ compiler is required for the Gromov-Wasserstein computation and may be required for the potpourri3d library if the precompiled binaries are not compatible with your system.
|
|
84
|
+
On Windows, we recommend Microsoft Visual C++ 14.0 or greater, which can be installed via the [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). On Ubuntu, it requires g++ and may require the package python3.x-dev, which registers the Python header files with g++.
|
|
85
|
+
|
|
86
|
+
----
|
|
87
|
+
|
|
88
|
+
The easiest way to run CAJAL is via [Jupyter](https://jupyter.org/). Install Jupyter with
|
|
89
|
+
```commandline
|
|
90
|
+
pip install notebook
|
|
91
|
+
```
|
|
92
|
+
Then start up Jupyter from terminal / Powershell using
|
|
93
|
+
```commandline
|
|
94
|
+
jupyter notebook
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Docker image
|
|
98
|
+
We provide two Docker images which contain CAJAL and its dependencies, ```cajal:minimal``` and ```cajal:maximal```. ```cajal:minimal``` is built on top of the Jupyter notebook Docker image ```base-notebook``` and contains only CAJAL and its dependencies, ```cajal:maximal``` is built on top of the Docker image ```tensorflow-notebook``` and contains numerous data science tools for further analysis of the output of CAJAL. Running the following command will launch a Jupyter notebook server on localhost with CAJAL and its dependencies installed:
|
|
99
|
+
```commandline
|
|
100
|
+
docker run -it -p 8888:8888 -v C:\Users\myusername\Documents\myfolder:/home/jovyan/work camaralab/cajal:maximal
|
|
101
|
+
```
|
|
102
|
+
The ```-p``` flag controls the port number on local host. For example, writing ```-p 4264:8888``` will let you access the Jupyter server from 127.0.0.1:4264. The ```-v``` "bind mount" flag allows one to mount a local directory on the host machine to a folder inside the container so that you can read and write files on the host machine from within the Docker image. Here one must mount the folder on the host machine as /home/jovyan/work or /home/jovyan/some_other_folder as the primary user "jovyan" in the Docker image only has access to that directory and to the /opt/conda folder. See the [Jupyter docker image documentation](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html) for more information.
|
|
103
|
+
|
|
104
|
+
## Documentation
|
|
105
|
+
Extensive documentation, including several tutorials, can be found in [CAJAL's readthedocs.io website](https://cajal.readthedocs.io/en/latest/index.html). This website is under development and will continue to be substantially updated during the coming months.
|
|
106
|
+
|
|
107
|
+
## New in this release (v1.0.0, 6/18/2024)
|
|
108
|
+
- Improved performance
|
|
109
|
+
- New functionality for intgerating multi-modal spaces using the WNN algorithm
|
|
110
|
+
- New functionality for visualizing consistency between morphological, electrophysiological, and transcriptomic cellular variation using ternary plots
|
|
111
|
+
- New functionality for visualizing local discrepancies between the morphologies of neurons
|
|
112
|
+
- Fixed several small bugs
|
cajal-1.0.0/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CAJAL <a href='https://github.com/CamaraLab/CAJAL'><img src="docs/images/logo.png" align="right" width="24%"/></a>
|
|
2
|
+
[](https://github.com/CamaraLab/CAJAL/actions/workflows/python-package.yml)
|
|
3
|
+
[](https://codecov.io/github/CamaraLab/CAJAL)
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
CAJAL is a Python library for multi-modal cell morphology analyses using Gromov-Wasserstein (GW) distance. Detailed information about the methods implemented in CAJAL can be found in:
|
|
7
|
+
|
|
8
|
+
K. W. Govek, P. Nicodemus, Y. Lin, J. Crawford, A. B. Saturnino, H. Cui, K. Zoga, M. P. Hart, P. G. Camara, _CAJAL enables analysis and integration of single-cell morphological data using metric geometry_. **Nature Communications** 14 (2023) 3672. [DOI:10.1038/s41467-023-39424-2](https://doi.org/10.1038/s41467-023-39424-2)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
Until we upload the package to PyPI, the pip installation works from GitHub:
|
|
12
|
+
```commandline
|
|
13
|
+
pip install git+https://github.com/CamaraLab/CAJAL.git
|
|
14
|
+
```
|
|
15
|
+
Installation on a standard desktop computer should take a few minutes.
|
|
16
|
+
|
|
17
|
+
----
|
|
18
|
+
|
|
19
|
+
A C++ compiler is required for the Gromov-Wasserstein computation and may be required for the potpourri3d library if the precompiled binaries are not compatible with your system.
|
|
20
|
+
On Windows, we recommend Microsoft Visual C++ 14.0 or greater, which can be installed via the [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). On Ubuntu, it requires g++ and may require the package python3.x-dev, which registers the Python header files with g++.
|
|
21
|
+
|
|
22
|
+
----
|
|
23
|
+
|
|
24
|
+
The easiest way to run CAJAL is via [Jupyter](https://jupyter.org/). Install Jupyter with
|
|
25
|
+
```commandline
|
|
26
|
+
pip install notebook
|
|
27
|
+
```
|
|
28
|
+
Then start up Jupyter from terminal / Powershell using
|
|
29
|
+
```commandline
|
|
30
|
+
jupyter notebook
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Docker image
|
|
34
|
+
We provide two Docker images which contain CAJAL and its dependencies, ```cajal:minimal``` and ```cajal:maximal```. ```cajal:minimal``` is built on top of the Jupyter notebook Docker image ```base-notebook``` and contains only CAJAL and its dependencies, ```cajal:maximal``` is built on top of the Docker image ```tensorflow-notebook``` and contains numerous data science tools for further analysis of the output of CAJAL. Running the following command will launch a Jupyter notebook server on localhost with CAJAL and its dependencies installed:
|
|
35
|
+
```commandline
|
|
36
|
+
docker run -it -p 8888:8888 -v C:\Users\myusername\Documents\myfolder:/home/jovyan/work camaralab/cajal:maximal
|
|
37
|
+
```
|
|
38
|
+
The ```-p``` flag controls the port number on local host. For example, writing ```-p 4264:8888``` will let you access the Jupyter server from 127.0.0.1:4264. The ```-v``` "bind mount" flag allows one to mount a local directory on the host machine to a folder inside the container so that you can read and write files on the host machine from within the Docker image. Here one must mount the folder on the host machine as /home/jovyan/work or /home/jovyan/some_other_folder as the primary user "jovyan" in the Docker image only has access to that directory and to the /opt/conda folder. See the [Jupyter docker image documentation](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html) for more information.
|
|
39
|
+
|
|
40
|
+
## Documentation
|
|
41
|
+
Extensive documentation, including several tutorials, can be found in [CAJAL's readthedocs.io website](https://cajal.readthedocs.io/en/latest/index.html). This website is under development and will continue to be substantially updated during the coming months.
|
|
42
|
+
|
|
43
|
+
## New in this release (v1.0.0, 6/18/2024)
|
|
44
|
+
- Improved performance
|
|
45
|
+
- New functionality for intgerating multi-modal spaces using the WNN algorithm
|
|
46
|
+
- New functionality for visualizing consistency between morphological, electrophysiological, and transcriptomic cellular variation using ternary plots
|
|
47
|
+
- New functionality for visualizing local discrepancies between the morphologies of neurons
|
|
48
|
+
- Fixed several small bugs
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
# Minimum requirements for the build system to execute
|
|
3
|
+
requires = [
|
|
4
|
+
"setuptools >= 70",
|
|
5
|
+
"pip>=24",
|
|
6
|
+
"wheel",
|
|
7
|
+
"Cython>=3",
|
|
8
|
+
"numpy"
|
|
9
|
+
]
|
|
10
|
+
# What should the build-backend be?
|
|
11
|
+
build-backend = "setuptools.build_meta"
|
|
12
|
+
|
|
13
|
+
[project]
|
|
14
|
+
name = "cajal"
|
|
15
|
+
version = "1.0.0"
|
|
16
|
+
description="A library for multi-modal cell morphology analyses using Gromov-Wasserstein (GW) distance."
|
|
17
|
+
readme="./README.md"
|
|
18
|
+
requires-python=">=3.9"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
authors= [ { name="Pablo Cámara", email='pcamara@pennmedicine.upenn.edu' } ]
|
|
22
|
+
classifiers=[
|
|
23
|
+
'License :: OSI Approved :: MIT License',
|
|
24
|
+
'Programming Language :: Python :: 3',
|
|
25
|
+
'Framework :: Jupyter',
|
|
26
|
+
'Topic :: Scientific/Engineering :: Bio-Informatics'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
dependencies = [
|
|
30
|
+
"igraph",
|
|
31
|
+
"leidenalg",
|
|
32
|
+
"networkx>=2.8.8",
|
|
33
|
+
"numpy",
|
|
34
|
+
"cython >= 3",
|
|
35
|
+
"pathos",
|
|
36
|
+
"tqdm>=4.64.1",
|
|
37
|
+
"potpourri3d",
|
|
38
|
+
"pynndescent>=0.5.13",
|
|
39
|
+
"python-louvain",
|
|
40
|
+
"scipy>=1.10",
|
|
41
|
+
"scikit-image",
|
|
42
|
+
"tifffile",
|
|
43
|
+
"trimesh",
|
|
44
|
+
"umap-learn>=0.5.3",
|
|
45
|
+
"mpltern>=1.0.0",
|
|
46
|
+
"scikit-dimension"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[project.optional-dependencies]
|
|
50
|
+
dev = [
|
|
51
|
+
"mypy>=0.991",
|
|
52
|
+
"pytest >= 7.2.1",
|
|
53
|
+
"pre-commit >= 2.20.0"
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
vis = [
|
|
57
|
+
"matplotlib >= 3.7.0",
|
|
58
|
+
"networkx",
|
|
59
|
+
"navis",
|
|
60
|
+
"mpltern"
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[project.license]
|
|
64
|
+
file="./LICENSE.md"
|
|
65
|
+
|
|
66
|
+
[project.urls]
|
|
67
|
+
git-repo="https://github.com/CamaraLab/CAJAL"
|
|
68
|
+
readthedocs="https://cajal.readthedocs.io/en/latest/"
|
|
69
|
+
biorxiv="https://www.biorxiv.org/content/10.1101/2022.05.19.492525v2"
|
|
70
|
+
|
|
71
|
+
[tool.black]
|
|
72
|
+
force-exclude = '''
|
|
73
|
+
/(
|
|
74
|
+
\.git
|
|
75
|
+
| \.mypy_cache
|
|
76
|
+
| _build
|
|
77
|
+
| build
|
|
78
|
+
| dist
|
|
79
|
+
| stubs
|
|
80
|
+
| pyproject.toml
|
|
81
|
+
| \.pre-commit-config.yaml
|
|
82
|
+
)/
|
|
83
|
+
'''
|
|
84
|
+
|
|
85
|
+
[tool.codespell]
|
|
86
|
+
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
|
|
87
|
+
skip = '.git*,*.css,pyproject.toml,data,swc,*.swc,obj,*.obj,*.pyi'
|
|
88
|
+
check-hidden = true
|
|
89
|
+
# embedded images into jupyter notebooks, acronyms and names starting with capital letter
|
|
90
|
+
ignore-regex = '(^\s*"image/\S+": ".*|\b([A-Z][a-zA-Z]+|scl/fo/|ser: Series|ot\.lp|networkx\.algorithms\.mis)\b)'
|
|
91
|
+
ignore-words-list = 'coo'
|
cajal-1.0.0/setup.cfg
ADDED
cajal-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
from Cython.Build import cythonize
|
|
3
|
+
import numpy
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
ROOT = os.path.abspath(os.path.dirname(__file__))
|
|
8
|
+
include_path = [numpy.get_include()]
|
|
9
|
+
|
|
10
|
+
setup(
|
|
11
|
+
ext_modules=cythonize(["src/cajal/*.pyx"]),
|
|
12
|
+
compiler_directives={"language_level": "3"},
|
|
13
|
+
include_dirs=include_path,
|
|
14
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* This file is a c++ wrapper function for computing the transportation cost
|
|
2
|
+
* between two vectors given a cost matrix.
|
|
3
|
+
*
|
|
4
|
+
* It was written by Antoine Rolet (2014) and mainly consists of a wrapper
|
|
5
|
+
* of the code written by Nicolas Bonneel available on this page
|
|
6
|
+
* http://people.seas.harvard.edu/~nbonneel/FastTransport/
|
|
7
|
+
*
|
|
8
|
+
* It was then modified to make it more amenable to python inline calling
|
|
9
|
+
*
|
|
10
|
+
* Please give relevant credit to the original author (Nicolas Bonneel) if
|
|
11
|
+
* you use this code for a publication.
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
#ifndef EMD_H
|
|
17
|
+
#define EMD_H
|
|
18
|
+
|
|
19
|
+
#include <iostream>
|
|
20
|
+
#include <vector>
|
|
21
|
+
#include <cstdint>
|
|
22
|
+
|
|
23
|
+
typedef unsigned int node_id_type;
|
|
24
|
+
|
|
25
|
+
enum ProblemType {
|
|
26
|
+
INFEASIBLE,
|
|
27
|
+
OPTIMAL,
|
|
28
|
+
UNBOUNDED,
|
|
29
|
+
MAX_ITER_REACHED
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
int myCMessage(int a,int b);
|
|
33
|
+
int EMD_wrap(int n1,int n2, double *X, double *Y,double *D, double *G, double* alpha, double* beta, double *cost, uint64_t maxIter);
|
|
34
|
+
int EMD_wrap_omp(int n1,int n2, double *X, double *Y,double *D, double *G, double* alpha, double* beta, double *cost, uint64_t maxIter, int numThreads);
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#endif
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/* This file is a c++ wrapper function for computing the transportation cost
|
|
2
|
+
* between two vectors given a cost matrix.
|
|
3
|
+
*
|
|
4
|
+
* It was written by Antoine Rolet (2014) and mainly consists of a wrapper
|
|
5
|
+
* of the code written by Nicolas Bonneel available on this page
|
|
6
|
+
* http://people.seas.harvard.edu/~nbonneel/FastTransport/
|
|
7
|
+
*
|
|
8
|
+
* It was then modified to make it more amenable to python inline calling
|
|
9
|
+
*
|
|
10
|
+
* Please give relevant credit to the original author (Nicolas Bonneel) if
|
|
11
|
+
* you use this code for a publication.
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
#include "network_simplex_simple.h"
|
|
17
|
+
#include "network_simplex_simple_omp.h"
|
|
18
|
+
#include "EMD.h"
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <stdio.h>
|
|
21
|
+
|
|
22
|
+
int myCMessage(int a, int b) { return a+b; }
|
|
23
|
+
|
|
24
|
+
int EMD_wrap(int n1, int n2, double *X, double *Y, double *D, double *G,
|
|
25
|
+
double* alpha, double* beta, double *cost, uint64_t maxIter) {
|
|
26
|
+
// beware M and C are stored in row major C style!!!
|
|
27
|
+
|
|
28
|
+
using namespace lemon;
|
|
29
|
+
uint64_t n, m, cur;
|
|
30
|
+
|
|
31
|
+
typedef FullBipartiteDigraph Digraph;
|
|
32
|
+
DIGRAPH_TYPEDEFS(Digraph);
|
|
33
|
+
|
|
34
|
+
// Get the number of non zero coordinates for r and c
|
|
35
|
+
n=0;
|
|
36
|
+
for (int i=0; i<n1; i++) {
|
|
37
|
+
double val=*(X+i);
|
|
38
|
+
if (val>0) {
|
|
39
|
+
n++;
|
|
40
|
+
}else if(val<0){
|
|
41
|
+
return INFEASIBLE;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
m=0;
|
|
45
|
+
for (int i=0; i<n2; i++) {
|
|
46
|
+
double val=*(Y+i);
|
|
47
|
+
if (val>0) {
|
|
48
|
+
m++;
|
|
49
|
+
}else if(val<0){
|
|
50
|
+
return INFEASIBLE;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Define the graph
|
|
55
|
+
|
|
56
|
+
std::vector<uint64_t> indI(n), indJ(m);
|
|
57
|
+
std::vector<double> weights1(n), weights2(m);
|
|
58
|
+
Digraph di(n, m);
|
|
59
|
+
NetworkSimplexSimple<Digraph,double,double, node_id_type> net(di, true, (int) (n + m), n * m, maxIter);
|
|
60
|
+
|
|
61
|
+
// Set supply and demand, don't account for 0 values (faster)
|
|
62
|
+
|
|
63
|
+
cur=0;
|
|
64
|
+
for (uint64_t i=0; i<n1; i++) {
|
|
65
|
+
double val=*(X+i);
|
|
66
|
+
if (val>0) {
|
|
67
|
+
weights1[ cur ] = val;
|
|
68
|
+
indI[cur++]=i;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Demand is actually negative supply...
|
|
73
|
+
|
|
74
|
+
cur=0;
|
|
75
|
+
for (uint64_t i=0; i<n2; i++) {
|
|
76
|
+
double val=*(Y+i);
|
|
77
|
+
if (val>0) {
|
|
78
|
+
weights2[ cur ] = -val;
|
|
79
|
+
indJ[cur++]=i;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
net.supplyMap(&weights1[0], (int) n, &weights2[0], (int) m);
|
|
85
|
+
|
|
86
|
+
// Set the cost of each edge
|
|
87
|
+
int64_t idarc = 0;
|
|
88
|
+
for (uint64_t i=0; i<n; i++) {
|
|
89
|
+
for (uint64_t j=0; j<m; j++) {
|
|
90
|
+
double val=*(D+indI[i]*n2+indJ[j]);
|
|
91
|
+
net.setCost(di.arcFromId(idarc), val);
|
|
92
|
+
++idarc;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
// Solve the problem with the network simplex algorithm
|
|
98
|
+
|
|
99
|
+
int ret=net.run();
|
|
100
|
+
uint64_t i, j;
|
|
101
|
+
if (ret==(int)net.OPTIMAL || ret==(int)net.MAX_ITER_REACHED) {
|
|
102
|
+
*cost = 0;
|
|
103
|
+
Arc a; di.first(a);
|
|
104
|
+
for (; a != INVALID; di.next(a)) {
|
|
105
|
+
i = di.source(a);
|
|
106
|
+
j = di.target(a);
|
|
107
|
+
double flow = net.flow(a);
|
|
108
|
+
*cost += flow * (*(D+indI[i]*n2+indJ[j-n]));
|
|
109
|
+
*(G+indI[i]*n2+indJ[j-n]) = flow;
|
|
110
|
+
*(alpha + indI[i]) = -net.potential(i);
|
|
111
|
+
*(beta + indJ[j-n]) = net.potential(j);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
return ret;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
int EMD_wrap_omp(int n1, int n2, double *X, double *Y, double *D, double *G,
|
|
127
|
+
double* alpha, double* beta, double *cost, uint64_t maxIter, int numThreads) {
|
|
128
|
+
// beware M and C are stored in row major C style!!!
|
|
129
|
+
|
|
130
|
+
using namespace lemon_omp;
|
|
131
|
+
uint64_t n, m, cur;
|
|
132
|
+
|
|
133
|
+
typedef FullBipartiteDigraph Digraph;
|
|
134
|
+
DIGRAPH_TYPEDEFS(Digraph);
|
|
135
|
+
|
|
136
|
+
// Get the number of non zero coordinates for r and c
|
|
137
|
+
n=0;
|
|
138
|
+
for (int i=0; i<n1; i++) {
|
|
139
|
+
double val=*(X+i);
|
|
140
|
+
if (val>0) {
|
|
141
|
+
n++;
|
|
142
|
+
}else if(val<0){
|
|
143
|
+
return INFEASIBLE;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
m=0;
|
|
147
|
+
for (int i=0; i<n2; i++) {
|
|
148
|
+
double val=*(Y+i);
|
|
149
|
+
if (val>0) {
|
|
150
|
+
m++;
|
|
151
|
+
}else if(val<0){
|
|
152
|
+
return INFEASIBLE;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Define the graph
|
|
157
|
+
|
|
158
|
+
std::vector<uint64_t> indI(n), indJ(m);
|
|
159
|
+
std::vector<double> weights1(n), weights2(m);
|
|
160
|
+
Digraph di(n, m);
|
|
161
|
+
NetworkSimplexSimple<Digraph,double,double, node_id_type> net(di, true, (int) (n + m), n * m, maxIter, numThreads);
|
|
162
|
+
|
|
163
|
+
// Set supply and demand, don't account for 0 values (faster)
|
|
164
|
+
|
|
165
|
+
cur=0;
|
|
166
|
+
for (uint64_t i=0; i<n1; i++) {
|
|
167
|
+
double val=*(X+i);
|
|
168
|
+
if (val>0) {
|
|
169
|
+
weights1[ cur ] = val;
|
|
170
|
+
indI[cur++]=i;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Demand is actually negative supply...
|
|
175
|
+
|
|
176
|
+
cur=0;
|
|
177
|
+
for (uint64_t i=0; i<n2; i++) {
|
|
178
|
+
double val=*(Y+i);
|
|
179
|
+
if (val>0) {
|
|
180
|
+
weights2[ cur ] = -val;
|
|
181
|
+
indJ[cur++]=i;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
net.supplyMap(&weights1[0], (int) n, &weights2[0], (int) m);
|
|
187
|
+
|
|
188
|
+
// Set the cost of each edge
|
|
189
|
+
int64_t idarc = 0;
|
|
190
|
+
for (uint64_t i=0; i<n; i++) {
|
|
191
|
+
for (uint64_t j=0; j<m; j++) {
|
|
192
|
+
double val=*(D+indI[i]*n2+indJ[j]);
|
|
193
|
+
net.setCost(di.arcFromId(idarc), val);
|
|
194
|
+
++idarc;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
// Solve the problem with the network simplex algorithm
|
|
200
|
+
|
|
201
|
+
int ret=net.run();
|
|
202
|
+
uint64_t i, j;
|
|
203
|
+
if (ret==(int)net.OPTIMAL || ret==(int)net.MAX_ITER_REACHED) {
|
|
204
|
+
*cost = 0;
|
|
205
|
+
Arc a; di.first(a);
|
|
206
|
+
for (; a != INVALID; di.next(a)) {
|
|
207
|
+
i = di.source(a);
|
|
208
|
+
j = di.target(a);
|
|
209
|
+
double flow = net.flow(a);
|
|
210
|
+
*cost += flow * (*(D+indI[i]*n2+indJ[j-n]));
|
|
211
|
+
*(G+indI[i]*n2+indJ[j-n]) = flow;
|
|
212
|
+
*(alpha + indI[i]) = -net.potential(i);
|
|
213
|
+
*(beta + indJ[j-n]) = net.potential(j);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
return ret;
|
|
220
|
+
}
|
|
File without changes
|