-
Notifications
You must be signed in to change notification settings - Fork 429
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
adding a new getitem method #2749
Conversation
Yeah - I like it! Could you please add a couple of tests of this new functionality? |
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #2749 +/- ##
=======================================
Coverage 83.92% 83.92%
=======================================
Files 132 132
Lines 18464 18493 +29
Branches 3014 3050 +36
=======================================
+ Hits 15495 15521 +26
- Misses 2226 2228 +2
- Partials 743 744 +1
|
I've added the tests, please review them. |
Sure |
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.
Thank you @shilpiprd,
I agree with @arokem concerning the tests. Can you also address the comments below? Thanks!
dipy/core/gradients.py
Outdated
idx = [idx] | ||
elif isinstance(idx, slice): | ||
idx = range(*idx.indices(len(self.bvals))) | ||
mask = self.bvals[idx] > 200 |
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.
Why 200? is it possible to get this value in a other way?
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.
You're right. I'll add a 'threshold' parameter to the definition against which values can be compared to create the mask.
dipy/core/gradients.py
Outdated
small_delta=0.01, | ||
b0_threshold=50, | ||
atol=1e-2, btens=None) | ||
#gave default value for small_delta, big_delta and b0_threshold |
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.
Why default value? I recommend to get the value already initialized like self.big_delta , self.small_delta , etc
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.
You're right. I'll change this as well.
I updated the getitem method, and realised that the test file needed to be changed as well.I changed the test file in this branch. Should I close the #2750 now? |
Yeah. I'll close the other one. |
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've thought about this a bit more. What do you think about indexing with a lower and upper bound on b-values?
dipy/core/gradients.py
Outdated
@@ -210,7 +210,25 @@ def bvecs(self): | |||
denom = self.bvals + (self.bvals == 0) | |||
denom = denom.reshape((-1, 1)) | |||
return self.gradients / denom | |||
|
|||
|
|||
def __getitem__(self, idx, threshold = 200): |
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 would set the threshold to be 0 per default.
One more thought is to implement a lower and upper bound, so that if you index:
gtab[:, 100:1000]
you would get a new gradient table with all the b-values between 100 and 1,000. I can see some use-cases for this kind of selection.
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 was thinking that we can probably remove the threshold argument and associated code, as it is no longer needed with the new indexing scheme.
Since now we could have: def getitem(self, bmin=0, bmax=np.inf):
And to create mask we can simply use: mask = (self.bvals >= bmin) & (self.bvals <= bmax). Using this to create mask we can remove a lot of unnecessary code as well.
and # Select b-values between 100 and 1000,
gtab = gtab[bmin=100, bmax=1000]
What do you think of this?
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 like the idea!
however, a deprecation cycle will be needed. a lot people are using this default behavior so we will have to keep both behavior for 1 year (2-3 releases) at least.
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.
So are you sugggesting something like this?
def getitem(self, bmin=0, bmax=np.inf, threshold=0):
# Use the new behavior if bmin and bmax are provided
if bmin != 0 or bmax != np.inf:
mask = (self.bvals >= bmin) & (self.bvals <= bmax)
else:
# Use the old behavior if bmin and bmax are not provided
mask = self.bvals > threshold
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.
Almost, something like:
from dipy.utils.deprecator import deprecated_params
...
@deprecated_params('threshold', None, since='1.17', until='1.19')
def getitem(self, bmin=0, bmax=np.inf, threshold=0):
if threshold and not bmin:
bmin = threshold
# priority to bmin in alll the other case
mask = (self.bvals >= bmin) & (self.bvals <= bmax)
...
Does it make sense for both of you @arokem? @shilpiprd ? (not tested, need to be checked)
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.
Oh right, so should i create a commit for this? I mean the method looks correct.
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.
yes, update the code and test it to make sure it works as expected.
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 modified the gradients file and tests_gradients.py as well. Please review it.
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.
Could somebody please manually trigger the checks on my last commit?
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 realised there were slight problems with the previous code. I've corrected them. Could somebody please review them. I think it should pass all the checks now.
Co-authored-by: Ariel Rokem <arokem@gmail.com>
The changes made in the file was not complete This reverts commit b6af6df.
The test file is passing all checks. It is failing one check but I can't seem to figure out where the error is because it says PASSED everywhere. |
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.
Hi @shilpiprd,
See below my comment and sorry for the late review.
dipy/core/gradients.py
Outdated
|
||
|
||
@deprecated_params('threshold', None, since='1.17', until='1.19') | ||
def getitem(self, bmin=0, bmax=np.inf, threshold=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.
I think, we got lost here.
The goal was to have the slicing capabilities. However, we loose it from your initial implementation.
we can not do anymore gtab[100:200].
we should get back to that. we just need a warning if the slicing is really different from the b0_treshold
.
Sorry for that. Can you revert your code, use __get_item__
, and in case of a slice, you check if the lower bound is similar to b0_thresold
. If yes, nothing to do, if no, just update self.b0_thresold to this value and warn the user
Does it make sense? we do not need(bmin, bmax, thresold)
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.
Sure, you're right. We did get deviated from the original method. I changed it, Did you mean something like this? If you'd agree with this, i'll change the test cases as well.
dipy/core/gradients.py
Outdated
if bmin != self.b0_threshold: | ||
self.b0_threshold = bmin | ||
warn("Updating b0_threshold to {} for slicing.".format(bmin), UserWarning, stacklevel=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.
yes, I mean something like this
dipy/core/gradients.py
Outdated
@@ -210,7 +211,26 @@ def bvecs(self): | |||
denom = self.bvals + (self.bvals == 0) | |||
denom = denom.reshape((-1, 1)) | |||
return self.gradients / denom | |||
|
|||
|
|||
def getitem(self, bmin=0, bmax=np.inf): |
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.
here it should be __get_item__(self, idx):
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.
Sure, I'll change this
dipy/core/gradients.py
Outdated
self.b0_threshold = bmin | ||
warn("Updating b0_threshold to {} for slicing.".format(bmin), UserWarning, stacklevel=2) | ||
# priority to bmin in all other cases | ||
mask = (self.bvals >= bmin) & (self.bvals <= bmax) |
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.
like you did before, check if slice
or just int
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'm sorry I didn't understand. Can u elaborate on what needs to be checked?
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.
Were you referring to bmin value?
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.
Oh, sorry. I understood what you meant.
I've added the idx parameter and modified the test file as well. Can someone please review it and allow for workflow checks to run? |
I noticed that the failing checks are not from the method that I"ve implemented. |
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.
Hi @shilpiprd,
Can you address my comments below? Thank you
dipy/core/gradients.py
Outdated
@@ -210,7 +211,35 @@ def bvecs(self): | |||
denom = self.bvals + (self.bvals == 0) | |||
denom = denom.reshape((-1, 1)) | |||
return self.gradients / denom | |||
|
|||
|
|||
def __get_item__(self, idx): |
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.
__getitem__
instead
dipy/core/tests/test_gradients.py
Outdated
gtab = GradientTable(gradients) | ||
|
||
# Test with a single index | ||
gtab_slice1 = gtab.__get_item__(1) |
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.
the goal was to do gtab[1]
for example
dipy/core/tests/test_gradients.py
Outdated
assert np.array_equal(gtab_slice1.bvecs, np.array([[1., 0., 0.]])) | ||
|
||
# Test with a range of indices | ||
gtab_slice2 = gtab.__get_item__(slice(2, 5)) |
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.
same, the goal is to do gtab[2:5]
and not gtab.__get_item__
.. Please can you update
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.
Sure
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.
It seems there was a typo in the test file. I changed it, it should pass all the tests now.
I don't think it's my method that's failing. It says 1 check failing, but inside it says PASSED for all. |
Thank you @shilpiprd, great job for your first contribution! it works like a charm. merging. |
I figured that get_item method is most closely related to gradients.py file which is inside dipy/core/gradients.py folder because i saw the bvech bvals method.
Example usage
#since we can call a getItem method by simply using square brackets,
gtab = MyGradientTable(gradients)
gtab_selected = gtab[2:10] # Select b-values from 2 to 10.
Please let me know if I need to make any changes to this method.