-
-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add python wrappings #1528
Merged
Merged
Add python wrappings #1528
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
213807e
to
2672faf
Compare
3722e47
to
0a2cbf4
Compare
5e32111
to
3c05bb4
Compare
Because there is a construct method, the base method is not inherited (shadowed).
Start adding factory functions to `__init__.py` to ease the construction of the wrapped types: Add `dgtal.Point(dim, dtype, data)`: `dgtal.Point` will return a `dgtal.kernel.Point2D` if `dim == 2` and `dtype == 'int32'`, or a `dgtal.kernel.Point3D` if `dim == 3` and `dtype == 'float'`. The `data` argument will be passed to the constructor, accepting list, tuples and `numpy.array`s of the right type and dimension.
```python dgtal.Domain(dim=2, lower_bound=dgtal.Point(dim=2).zero, upper_bound=dgtal.Point(dim=2).diagonal(2)) ```
Also include PreCell and SPreCell helpers.
Accepting dim, and max_norm parameters
Change py::arg("props") for "properties" in `DigitalTopology` for consistency. Also add static method: `adjacency_pair_string` to the python wrappings of Digital Topology. MetricAdjacency `__str__` now shows typestr (Adj8, Adj26, etc.)
Works with np.arrays as well. The check of valid dimensions, only 2 or 3 allowed is still in place.
The problem was with CowPtr. Solved using `const TT`, which force CowPtr to avoid the copy. Same solution for `topology()` method.
In `foreground()`, and `background()` methods. These `MetricAdjacency` members are references and non-copyable. ``` RuntimeError: return_value_policy = copy, but type DGtal::MetricAdjacency<DGtal::SpaceND<2u, int>, 2u, 2u> is non-copyable! ``` Set `py::return_value_policy::reference_internal` instead of automatic (it was doing copies)
Accepts domain, or data as a numpy.array Test factory added in test_ImageContainerBySTLVector
CI failed with the following error: ``` /home/travis/build/DGtal-team/DGtal/src/DGtal/topology/CubicalComplex.h:556: warning: argument 'set' of command @param is not found in the argument list of DGtal::VoxelComplex< TKSpace, TCellContainer >::construct(typename TDigitalSet) ``` It's a bug in Doxygen, workorounded to pass CI
```bash ./wrap/deploy/increase_version.py --no-write incrementing version component: patch | version_index: 2 current_version: 0.0.1 final_version: 0.0.2 Not writing to any file, remove -n or --no-write argument if wanted. ```
``` print("Python: Increase version ({}) to {}.".format(args.version_component, final_version_str)) ``` ``` ```
🚀 |
dcoeurjo
approved these changes
Feb 15, 2021
all green.. thanks a lot @phcerdan |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
PR Description
DGtal is wrapped to python using pybind11, and uploaded regularly to pypi for all platforms (Linux, Windows, MacOS)
and multiple
python
version (from3.5
to latest) using azure-pipelines.Development
Due to the heavy templated nature of DGtal, only a subset of types
are available in Python. All the types in Z2i and Z3i namespaces are wrapped, they are defined in StdDefs.h.
Steps to add a new wrap:
Imagine we want to add wrappings for the class
HyperRectDomain
from thekernel
module.Inside the folder
wrap/kernel
add the files:HyperRectDomain_types_py.h
, to add (and reuse later) the specific types ofHyperRectDomain
that are going to be wrapped into python.HyperRectDomain_py.cpp
. This is the file to compile where we define the functioninit_HyperRectDomain
.Using the types from HyperRectDomain_types_py we wrap that type with the template function
declare_HyperRectDomain
.HyperRectDomain_declare_py.h
. This is where the templated function declare_HyperRectDomain is defined, and where the actual pybind11 wrappings are done.Add a call to
init_HyperRectDomain
to theinit_dgtal_kernel
function inside thekernel_init.cpp
.If you are adding a new module, i.e.
foo
, the modulefoo
has to be added to the parent init filedgtal_init_py.cpp
in thewrap
folder.All this modularity allows parallel compilation to speed up the build process.
Add the
.cpp
files to the apropiateCMakeLists.txt
.In this case we add
HyperRectDomain_py.cpp
towrap/kernel/CMakeLists.txt
.In the case we are adding a new module, use
add_subdirectory(foo)
inwrap/CMakeLists.txt
Add python tests for your new wraps.
Add the file
test_HyperRectDomain.py
towrap/test/kernel
, and usingpytest
exercise all the constructors, functions and access to data members exposed in your wrap.Also, add the test file to
wrap/test/kernel/CMakeLists.txt
to allowctest
to discover and execute the test.You can then
ctest -R test_Hyper* -V
to execute all the tests in that file.Please remember that pytest requires that your test functions start with
test_
, for exampledef test_constructors():
.Also,
pytest
allows to parametrize your test functions, allowing to test the wrappings for multiple types automatically.See existing examples to guide you in the process.
Classes wrapped
StdDefs:
Point2D
,Point3D
,RealPoint2D
,RealPoint3D
DomainZ2i
,DomainZ3i
DigitalSetZ2i
,DigitalSetZ3i
PreCell2D
,SPreCell2D
,KPreSpace2D
(and 3D)Cell2D
,SCell2D
,KSpace2D
(and 3D)Adj4
,Adj8
, 3D:Adj6
,Adj18
,Adj26
DT4_8
,DT8_4
,DT6_18
,DT18_6
,DT6_26
,DT26_6
Object4_8
,Object8_4
,Object6_18
,Object18_6
,Object6_26
,Object26_6
IO:
Check test_ImageContainerBySTLVector.py for usage, in a nutshell:
Use external library (ITK, opencv) and use their numpy bridge.
Other:
CubicalComplex2D
,CubicalComplex3D
(usingstd::unordered_map
as CellContainer).VoxelComplex
(3D-only)Factory functions
Factory functions are defined in
__init__.py
to ease the construction of the wrapped types:dgtal.Point(dim, dtype, data)
dgtal.Point
will return adgtal.kernel.Point2D
ifdim == 2
anddtype == 'int32'
, or adgtal.kernel.Point3D
if
dim == 3
anddtype == 'float'
. Thedata
argument will be passed to the constructor, accepting list,tuples and
numpy.array
s of the right type and dimension.Also:
dgtal.Point(data=[2,3])
will return adgtal.kernel.Point2D
, dimension will be inferred.dgtal.Domain(lower_bound, upper_bound)
dgtal.DigitalSet(domain)
dgtal.KPreSpace(dim)
dgtal.PreCell(dim, point)
, SPreCell:dgtal.PreCell(dim, point, positive)
dgtal.KSpace(dim)
dgtal.MetricAdjacency(dim, max_norm)
.Example:
adj26 = dgtal.MetricAdjacency(dim=3, max_norm=3)
dgtal.DigitalTopology(foreground, background, properties)
dgtal.Object(topology, domain, point_set, connectedness)
dgtal.ImageContainer(dtype, domain, data, lower_bound_ijk)
Dev notes
data()
to DigitalSetBySTLVector.h, to expose low level details to python.This would allow slicing, pickling, copy, setitem, getitem and other python goodies.
Instead of
data()
, we addcontainer()
to DigitalSets and ImageContainers PR Add container member function to DigitalSets and ImageContainers #1532Building wraps
Compile DGtal with option
DGTAL_WRAP_PYTHON=ON
.This will create a folder in your build tree named
dgtal
.From the build folder this will work:
python -c 'import dgtal'
, to use the package from the build tree elswhere, create a virtualenviroment:And then create a file named:
dgtal.pth
in~/.virtualenvs/dgtal-build/lib/python3.X/site-packages
with the content:Now you can use
workon dgtal-build
from anywhere, andpython -c 'import dgtal'
will work.Remember that if you modify and rebuild DGtal wrappings, and you are in a
ipython
session, orjupyter
, you will need to restart or reloadthe ipython kernel for the changes to be loaded.
Releasing to pypi
Setup
It is recommended that you setup a virtual environment for deploy, so
azure-cli
andtwine
do not have to be installed in the system python.For azure download
Read this for how-to.
pip install azure-cli
for azure commands.For pypi upload
pip install twine
for easy upload.Download the wheels from Azure (Linux/MacOS only)
First, login into azure if you haven't already, using your PersonalAccessToken.
Then, go to the pipeline PythonDeploy, and select the commit from where you want the wheels.
In the URL
https://dev.azure.com/davidcoeurjolly/DGtal/_build/results?buildId=246&view=results
, grab thebuildId
number, in this case:246
.With that id, use the script download_azure_artifacts.sh located in
dgtal-src/wrap/deploy/download_azure_artifacts.sh
.All the wheels for all platforms and all python versions will be downloaded to
/tmp/dist
.Upload to pypi
For testing that the package complies with all requisites, you might want to first upload to test.pypi.
Increase version in dgtalVersion.py
After manual deployment to pypi, don't forget to increase the version in wrap/deploy/dgtalVersion.py.
A package with the same version cannot be uploaded to pypi (i.e. cannot override).
The provided python script increase_version.py can increment the version automatically:
By default the script increase the
patch
version. You can increment bigger components with-c minor
or-c major
. Use--help
for other options.Remove the
--no-write
option to commit the new version to the filedgtalVersion.py
.Checklist
cmake
mode (otherwise, Travis C.I. will fail).