-
Notifications
You must be signed in to change notification settings - Fork 437
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
QuickBundlesX #1434
QuickBundlesX #1434
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, QuickBundles(threshold)
and QuickBundlesX(thresholds=[threshold])
should produce the same kind of results. Maybe we could refactor QuickBundles such that it uses the same Cython algorithm/code as QuickBundlesX (or maybe in a future PR). In any cases, we add some simple tests that check if the results are similar between QuickBundles(threshold)
and QuickBundlesX(thresholds=[threshold])
.
dipy/segment/clustering.py
Outdated
thresholds=self.thresholds, | ||
ordering=ordering) | ||
|
||
#cluster_map.refdata = streamlines |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment.
dipy/segment/clusteringspeed.pyx
Outdated
DEF BIGGEST_FLOAT = 3.4028235e+38 # np.finfo('f4').max | ||
DEF SMALLEST_FLOAT = -3.4028235e+38 # np.finfo('f4').max | ||
|
||
THRESHOLD_MULTIPLIER = 2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused.
dipy/segment/clusteringspeed.pyx
Outdated
@@ -99,7 +402,7 @@ cdef class ClustersCentroid(Clusters): | |||
raise ValueError("'centroid_shape' must be a tuple or a int.") | |||
|
|||
self._centroid_shape = tuple2shape(centroid_shape) | |||
|
|||
# self.aabb |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line.
@@ -175,6 +478,10 @@ cdef class ClustersCentroid(Clusters): | |||
converged &= fabs(centroid[n, d] - updated_centroid[n, d]) < self.eps | |||
centroid[n, d] = updated_centroid[n, d] | |||
|
|||
#cdef float * aabb = &self.centroids[id_cluster].aabb[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line.
dipy/segment/clusteringspeed.pyx
Outdated
self.metric = metric | ||
self.features_shape = tuple2shape(features_shape) | ||
self.threshold = threshold | ||
self.max_nb_clusters = max_nb_clusters | ||
self.clusters = ClustersCentroid(features_shape) | ||
self.features = np.empty(features_shape, dtype=DTYPE) | ||
self.features_flip = np.empty(features_shape, dtype=DTYPE) | ||
self.bvh = bvh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nowhere in the code, I could find Quickbundles instance with bvh=1
. Maybe we should remove this functionality for now? Otherwise, we could do like for QuickbundlesX and always perform aabb checks?
dipy/segment/clusteringspeed.pyx
Outdated
return self._build_clustermap() | ||
|
||
|
||
def evaluate_aabbb_checks(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't find a place where this function is used.
dipy/segment/tests/test_qbx.py
Outdated
#test_show_qbx() | ||
#test_3D_segments() | ||
test_3D_points() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline missing?
dipy/segment/tests/test_qbx.py
Outdated
thresholds = [4, 2, 1] | ||
qbx_class = QuickBundlesX(thresholds) | ||
qbx = qbx_class.cluster(points) | ||
print(qbx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we expect? Add assertions.
dipy/segment/tests/test_qbx.py
Outdated
thresholds = [4, 2, 1] | ||
qbx_class = QuickBundlesX(thresholds) | ||
qbx = qbx_class.cluster(points) | ||
print(qbx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we expect? Add assertions.
Codecov Report
@@ Coverage Diff @@
## master #1434 +/- ##
==========================================
+ Coverage 87.38% 87.41% +0.02%
==========================================
Files 237 238 +1
Lines 30069 30282 +213
Branches 3232 3253 +21
==========================================
+ Hits 26277 26472 +195
- Misses 3043 3057 +14
- Partials 749 753 +4
Continue to review full report at Codecov.
|
Hey @MarcCote I agree on the bvh. Needs some investigation. Any clues on the travis error? Strangely only one bot is failing https://travis-ci.org/nipy/dipy/jobs/343108569 |
The last bot is failing because of the new version of Cython. Look at the issue #1435 |
@MarcCote there is a change in Cython that will require some large RF of the code. Cython stopped supporting memory views in structs. |
dipy/segment/cythonutils.pyx
Outdated
@@ -104,3 +111,46 @@ cdef int same_shape(Shape shape1, Shape shape2) nogil: | |||
same_shape &= shape1.dims[i] == shape2.dims[i] | |||
|
|||
return same_shape | |||
|
|||
|
|||
cdef Data2D* create_memview(Py_ssize_t buffer_size, Py_ssize_t dims[MAX_NDIM]) nogil: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we only want to support 2D memview? If so, we could rename the function so that it is clearer it is only for 2D array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, you are right, let's do it more generic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally, I choose the easy path: renaming. The second option needs more thinking and we need to move forward with the release
""" | ||
free(&(memview[0][0, 0])) | ||
memview[0] = None # Necessary to decrease refcount | ||
free(memview) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newline missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
Rb qbx2 2
@MarcCote I addressed all your comments. If Travis agrees do merge this PR so that the other PRs can can start becoming green. |
Yeah! Looks good and all tests are happy. I think it is ready to merge, can you have a last look @MarcCote? Thanks to you and @Garyfallidis! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After that, LGTM.
dipy/segment/tests/test_qbx.py
Outdated
def test_circle_parallel_fornix(): | ||
|
||
circle = streamlines_in_circle(100, step_size=2) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PEP8 - too many empty lines.
dipy/segment/clusteringspeed.pyx
Outdated
self.level = levels[level] | ||
self.traverse_postorder(self.root, self._fetch_level) | ||
return self.clusters | ||
# cdef void _fetch_level(self, CentroidNode* node): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's delete those commented lines if everyone is happy with manipulating the TreeClusterMap python object instead of the QuickBundlesX Cython object.
dipy/segment/clusteringspeed.pxd
Outdated
@@ -110,5 +110,5 @@ cdef class QuickBundlesX(object): | |||
cpdef object insert(self, Data2D datum, int datum_idx) | |||
cdef void traverse_postorder(self, CentroidNode* node, void (*visit)(QuickBundlesX, CentroidNode*)) | |||
cdef void _dealloc_node(self, CentroidNode* node) | |||
cdef void _fetch_level(self, CentroidNode* node) | |||
# cdef void _fetch_level(self, CentroidNode* node) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete
Done @MarcCote ! |
Let's make all the PRs green again! |
Super! @skoudoro please inform everyone to rebase their PRs. We can go green again :) Thank you both for all the help. That was a fast recovery with a sudden Cythonic change! Grrr..... |
QuickBundlesX
This PR is replacing #1380
This PR includes the fastest algorithm ever for clustering tractograms!!! 🔥
Garyfallidis E. et al. QuickBundlesX: Sequential clustering of millions of streamlines in multiple levels of detail at record execution time. Proceedings of the, International Society of Magnetic Resonance in Medicine (ISMRM). Singapore, 4187, 2016.