diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 41bd002d..4ae6c2b9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -71,7 +71,7 @@ When you run `python -m pip install .` or `python -m pip install -e .` to instal
## Wrapping ANTs functions
-Wrapping an ANTs function is easy since pybind11 implicitly casts between python and C++ standard types, allowing you to directly interface with C++ code. Here's an example:
+Wrapping an ANTs function is easy since nanobind implicitly casts between python and C++ standard types, allowing you to directly interface with C++ code. Here's an example:
Say we want to wrap the `Atropos` function. We create the following file called
`WRAP_Atropos.cxx` in the `src/` directory:
@@ -97,7 +97,7 @@ void wrap_Atropos(nb::module_ &m)
}
```
-The `WRAP_function.cxx` file is the SAME for every ANTs function - simply exchange the word "Atropos" with whatever the function name is.
+The `WRAP_Atropos.cxx` file is the same for every ANTs function - simply exchange the word "Atropos" with whatever the function name is and include the correct file.
Next, we add the following two lines to the top of the `src/main.cpp` file:
@@ -118,22 +118,23 @@ The general workflow for wrapping a library calls involves the following steps:
- write a wrapper python function (e.g. `def atropos(...)`)
- build up a list or dictionary of string argument names as in ANTs
-- pass those raw arguments through the function `process_arguments(args)`
-- pass those processed arguments into the library call (e.g. `lib.Atropos(processed_args)`).
+- pass those raw arguments through the function `myargs = process_arguments(args)`
+- get the library function by calling `libfn = get_lib_fn('Atropos')`
+- pass those processed arguments into the library function (e.g. `libfn(myargs)`).
## Adding C++ / ITK code
-You can write any kind of custom code to process antspy images. The underlying image is ITK so the AntsImage class holds a pointer to the underlying ITK object in the in the property `self.pointer`.
+You can write any kind of custom code to process images in ANTsPy. The ANTsImage class holds a pointer to the underlying ITK object in the in the property `self.pointer`.
-To go from a C++ ANTsImage class to an ITK image, pass in an `AntsImage` argument (`image.pointer` in python) and call `.ptr` to access the ITK image.
+To go from a C++ ANTsImage to an ITK image, pass in an `AntsImage` argument (`image.pointer` in python) and call `.ptr` to access the ITK image.
```cpp
#include "antsImage.h"
template
-ImageType::Pointer getITKImage( AntsImage antsImage )
+ImageType::Pointer getITKImage( AntsImage & antsImage )
{
typedef typename ImageType::Pointer ImagePointerType;
ImagePointerType itkImage = antsImage.ptr;
@@ -166,7 +167,7 @@ We would create the following file `src/getOrigin.cxx`:
// all functions accepted ANTsImage types must be templated
template
-std::vector getOrigin( AntsImage antsImage )
+std::vector getOrigin( AntsImage & antsImage )
{
// cast to ITK image as shown above
typedef typename ImageType::Pointer ImagePointerType;
@@ -218,9 +219,9 @@ from ants.decorators import image_method
from ants.internal import get_lib_fn
@image_method
-def get_origin(img):
+def get_origin(image):
libfn = get_lib_fn('getOrigin')
- origin = libfn(img.pointer)
+ origin = libfn(image.pointer)
return tuple(origin)
```
@@ -238,7 +239,7 @@ Here is an example:
#include "antsImage.h"
template
-AntsImage someFunction( AntsImage antsImage )
+AntsImage someFunction( AntsImage & antsImage )
{
// cast from ANTsImage to ITK Image
typedef typename ImageType::Pointer ImagePointerType;
@@ -281,7 +282,7 @@ AntsImage someFunction( AntsImage antsImage )
## Adding Python code
-If you want to add custom Python code that calls other ANTsPy functions or the wrapped code, there are a few things to know. The `label_clusters` function provides a good example to show how to do so.
+If you want to add custom Python code that calls other ANTsPy functions or the wrapped code, there are a few things to know. The `label_clusters` function provides a good example of how to do so.
```python
import ants
@@ -294,10 +295,8 @@ def label_clusters(image, min_cluster_size=50, min_thresh=1e-6, max_thresh=1, fu
This will give a unique ID to each connected
component 1 through N of size > min_cluster_size
"""
- dim = image.dimension
clust = ants.threshold_image(image, min_thresh, max_thresh)
- temp = int(fully_connected)
- args = [dim, clust, clust, min_cluster_size, temp]
+ args = [image.dimension, clust, clust, min_cluster_size, int(fully_connected)]
processed_args = process_arguments(args)
libfn = get_lib_fn('LabelClustersUniquely')
libfn(processed_args)
@@ -328,30 +327,11 @@ With those three imports, you can call any internal Python function or any C++ f
## Running tests
-All tests can be executed by running the following command from the main directory:
+Whenever you add or change code in a meaningful way, you should add tests. All tests can be executed by running the following command from the main project directory:
```bash
sh ./tests/run_tests.sh
```
-
-Similarly, code coverage can be calculated by adding a flag to the above command:
-
-```bash
-sh ./tests/run_tests.sh -c
-```
-
-This will create an html folder in the `tests` directory with detailed coverage information.
-In order to publish this information to coveralls, we run the following (given that the
-.coveralls.yml file is in the tests directory with the correct repo token):
-
-```bash
-./tests/run_tests.sh -c
-cd tests
-coveralls
-```
-
-We use https://coveralls.io/ for hosting our coverage information.
-
Refer to that file for adding tests. We use the `unittest` module for creating tests, which
generally have the following structure: