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
Make PeaksAndMetrics pickle-able #1195
Conversation
Travis failure unrelated to this PR, and only on Python 3.3 |
Further explanation : https://snorfalorpagus.net/blog/2016/04/16/pickling-cython-classes |
@@ -38,6 +38,10 @@ cdef class PeaksAndMetricsDirectionGetter(DirectionGetter): | |||
self.ang_thr = 60 | |||
self.total_weight = .5 | |||
|
|||
def __getstate__(self): return self.__dict__ | |||
|
|||
def __setstate__(self, d): self.__dict__.update(d) |
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 update
will leave any previous members in place, that are not defined in d
. Is that the right thing to do?
Thanks for finding that post!
Do you understand why we don't see this in other versions of Python? Seems
like we should have been getting this as far back as at least 3.4.
…On Mon, Mar 20, 2017 at 11:14 AM, Matthew Brett ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In dipy/reconst/peak_direction_getter.pyx
<#1195 (comment)>:
> @@ -38,6 +38,10 @@ cdef class PeaksAndMetricsDirectionGetter(DirectionGetter):
self.ang_thr = 60
self.total_weight = .5
+ def __getstate__(self): return self.__dict__
+
+ def __setstate__(self, d): self.__dict__.update(d)
The update will leave any previous members in place, that are not defined
in d. Is that the right thing to do?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNiTzfk2CVuZN6pwgXO-nTSLPkpVDks5rnsHogaJpZM4Min2V>
.
|
No, that is puzzling. I wonder whether it's something random about when classes get thrown around by the multiprocessing ? |
Sorry - I hate to say - but it would be good to have a test of pickling and unpickling these guys in fresh and used state. |
Codecov Report
@@ Coverage Diff @@
## master #1195 +/- ##
==========================================
+ Coverage 85.93% 85.94% +<.01%
==========================================
Files 219 219
Lines 26403 26419 +16
Branches 2711 2716 +5
==========================================
+ Hits 22689 22705 +16
+ Misses 3052 3050 -2
- Partials 662 664 +2
Continue to review full report at Codecov.
|
To answer the other thing: From reading the documentation, it seems that
maybe we don't even need to implement `__setstate__`, so I have removed
that one.
…On Mon, Mar 20, 2017 at 11:16 AM, Ariel Rokem ***@***.***> wrote:
Thanks for finding that post!
Do you understand why we don't see this in other versions of Python? Seems
like we should have been getting this as far back as at least 3.4.
On Mon, Mar 20, 2017 at 11:14 AM, Matthew Brett ***@***.***>
wrote:
> ***@***.**** commented on this pull request.
> ------------------------------
>
> In dipy/reconst/peak_direction_getter.pyx
> <#1195 (comment)>:
>
> > @@ -38,6 +38,10 @@ cdef class PeaksAndMetricsDirectionGetter(DirectionGetter):
> self.ang_thr = 60
> self.total_weight = .5
>
> + def __getstate__(self): return self.__dict__
> +
> + def __setstate__(self, d): self.__dict__.update(d)
>
> The update will leave any previous members in place, that are not
> defined in d. Is that the right thing to do?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#1195 (review)>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AAHPNiTzfk2CVuZN6pwgXO-nTSLPkpVDks5rnsHogaJpZM4Min2V>
> .
>
|
Yes. Fair enough. Since I just did that in a notebook, to be sure that I am
not messing anything up, may as well add this to the tests... Coming!
…On Mon, Mar 20, 2017 at 11:19 AM, Matthew Brett ***@***.***> wrote:
Sorry - I hate to say - but it would be good to have a test of pickling
and unpickling these guys in fresh and used state.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNgTCBaO6RelQ6EBV8_XtOKXgvz1Tks5rnsNAgaJpZM4Min2V>
.
|
OK - here it is. Let's see if I managed to write something that works on
both Python 2 and Python 3...
…On Mon, Mar 20, 2017 at 11:21 AM, Ariel Rokem ***@***.***> wrote:
Yes. Fair enough. Since I just did that in a notebook, to be sure that I
am not messing anything up, may as well add this to the tests... Coming!
On Mon, Mar 20, 2017 at 11:19 AM, Matthew Brett ***@***.***>
wrote:
> Sorry - I hate to say - but it would be good to have a test of pickling
> and unpickling these guys in fresh and used state.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#1195 (comment)>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AAHPNgTCBaO6RelQ6EBV8_XtOKXgvz1Tks5rnsNAgaJpZM4Min2V>
> .
>
|
Following roughly this idea: http://stackoverflow.com/a/12712509/3532933
Checking that switching on and off some of the requested returns still de-/serializes properly.
I'm learning so many things about pickles over here 😄 Previous attempt seemed to be failing on Python 2. Here's a new approach that might work on both. |
Changing the title of the PR accordingly 😉 |
dipy/direction/peaks.py
Outdated
@@ -157,8 +157,63 @@ def peak_directions(odf, sphere, relative_peak_threshold=.5, | |||
return directions, values, indices | |||
|
|||
|
|||
def _rebuild_pam(sphere, peak_indices, peak_values, peak_dirs, |
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 not make this a classmethod called from_params
or similar?
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 would be a bit weird as a class method, considering that it returns another instance of that class. Or would it?
There does seem to be an opportunity to reduce boiler-plate here though, so I am going to try out a couple more things. Stand by.
What do you think about this? I renamed it to |
And I think this looks better than:
which is what we would do if we had this implemented as a class method (I think). |
The floating external function looks funny to me, especially for a class that is otherwise empty. Here's the alternative classmethod I was thinking of:
To me it looks like a normal alternative class constructor pattern... |
Gotcha. How's this?
…On Tue, Mar 21, 2017 at 9:27 AM, Matthew Brett ***@***.***> wrote:
The floating external function looks funny to me, especially for a class
that is otherwise empty.
Here's the alternative classmethod I was thinking of:
pam = PeaksAndMetrics()
pam = PeaksAndMetrics.from_attrs(...)
To me it looks like a normal alternative class constructor pattern...
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNqqB5cFWz7rMV4ovzdv-zF6e-t5wks5rn_qGgaJpZM4Min2V>
.
|
Sadly, this approach does not work on Python 2: https://travis-ci.org/arokem/dipy/jobs/213491090#L2580 Any ideas? |
On Wed, Mar 22, 2017 at 11:50 AM, Matthew Brett ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In dipy/direction/peaks.py
<#1195 (comment)>:
> @@ -157,8 +157,64 @@ def peak_directions(odf, sphere, relative_peak_threshold=.5,
return directions, values, indices
+def _pam_from_attrs(sphere, peak_indices, peak_values, peak_dirs,
Consider adding class as first argument? Or as optional argument at end?
In case we need to sub-class?
Sorry to ask, but why do we need this otherwise empty sub-class?
class PeaksAndMetrics(PeaksAndMetricsDirectionGetter): pass
Why not use PeaksAndMetricsDirectionGetter directly?
I'm not sure why we are subclassing here.
I added another argument for sub-classing purposes, with PeaksAndMetrics as
the default value.
… —
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNstK6GtBOdQXyPzghArKUlCD1MhGks5roW1rgaJpZM4Min2V>
.
|
self.qa, | ||
self.shm_coeff, | ||
self.B, | ||
self.odf) |
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.
Add self.__class__
as argument to allow sub-classing? Maybe, it would be better as first argument.
Yup. Moved to first argument.
…On Wed, Mar 22, 2017 at 12:32 PM, Matthew Brett ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In dipy/direction/peaks.py
<#1195 (comment)>:
> @@ -157,8 +157,20 @@ def peak_directions(odf, sphere, relative_peak_threshold=.5,
return directions, values, indices
+class PeaksAndMetrics(PeaksAndMetricsDirectionGetter):
+ def __reduce__(self): return _pam_from_attrs, (self.sphere,
+ self.peak_indices,
+ self.peak_values,
+ self.peak_dirs,
+ self.gfa,
+ self.qa,
+ self.shm_coeff,
+ self.B,
+ self.odf)
Add self.__class__ as argument to allow sub-classing? Maybe, it would be
better as first argument.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNvBDV_x6hWndgXUBl7Pm_dehf4Qtks5roXdNgaJpZM4Min2V>
.
|
dipy/direction/peaks.py
Outdated
|
||
Parameters | ||
---------- | ||
klass : class, optional |
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.
No longer optional !
All OK for me, after fix of |
Good catch. Thanks!
…On Wed, Mar 22, 2017 at 1:19 PM, Matthew Brett ***@***.***> wrote:
All OK for me, after fix of optional in docstring.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNohi8DTN73w_4yPYMEPmbaD1dRuOks5roYJCgaJpZM4Min2V>
.
|
dipy/direction/peaks.py
Outdated
|
||
return pam | ||
return _pam_from_attrs(PeaksAndMetrics, sphere, peak_indices, peak_values, |
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 guess, if you can be bothered:
return _pam_from_attrs(PeaksAndMetrics,
sphere,
peak_indices,
peak_values,
peak_dirs,
gfa_array,
qa_array,
shm_coeff if return_sh else None,
B if return_sh else None,
odf_array if return_odf else None)
I can always be bothered
…On Wed, Mar 22, 2017 at 2:19 PM, Matthew Brett ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In dipy/direction/peaks.py
<#1195 (comment)>:
>
- return pam
+ return _pam_from_attrs(PeaksAndMetrics, sphere, peak_indices, peak_values,
I guess, if you can be bothered:
return _pam_from_attrs(PeaksAndMetrics,
sphere,
peak_indices,
peak_values,
peak_dirs,
gfa_array,
qa_array,
shm_coeff if return_sh else None,
B if return_sh else None,
odf_array if return_odf else None)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNm74w010ktnrBIrBdBSYY4IfFJi8ks5roZBIgaJpZM4Min2V>
.
|
Ah sorry - I mean particularly cleaning up the slightly ugly if blocks with the conditionals:
|
Oops. I didn't really bother reading all the way down :-)
Fixed now.
…On Wed, Mar 22, 2017 at 2:37 PM, Matthew Brett ***@***.***> wrote:
Ah sorry - I mean particularly cleaning up the slightly ugly if blocks
with the conditionals:
...
shm_coeff if return_sh else None,
B if return_sh else None,
odf_array if return_odf else None)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1195 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNlIKWOUo6AabbIWW-bH672K2YfvWks5roZSTgaJpZM4Min2V>
.
|
Thanks for your patience. One of us merge when the tests pass (apart from the 3.3 failure)? |
The patience is all yours. Last one to the merge button is a rotten egg. |
Beat you to it! |
Good job - but - aren't the tests still running? |
I think not: https://travis-ci.org/arokem/dipy/builds/214021129
…On Wed, Mar 22, 2017 at 4:47 PM, Matthew Brett ***@***.***> wrote:
Good job - but - aren't the tests still running?
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#1195 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAHPNu7BfJeAVc72f7C-3IeH-tRlQNtyks5robMVgaJpZM4Min2V>
.
|
Addmitedly, I cheated a little bit, because I have Travis looking over my
own fork as well :-)
…On Wed, Mar 22, 2017 at 4:49 PM, Ariel Rokem ***@***.***> wrote:
I think not: https://travis-ci.org/arokem/dipy/builds/214021129
On Wed, Mar 22, 2017 at 4:47 PM, Matthew Brett ***@***.***>
wrote:
> Good job - but - aren't the tests still running?
>
> —
> You are receiving this because you modified the open/close state.
> Reply to this email directly, view it on GitHub
> <#1195 (comment)>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AAHPNu7BfJeAVc72f7C-3IeH-tRlQNtyks5robMVgaJpZM4Min2V>
> .
>
|
Well played sir. |
Make PeaksAndMetrics pickle-able
Might help with #1190
See: http://stackoverflow.com/a/2050357/3532933