-
Notifications
You must be signed in to change notification settings - Fork 29
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
xapyb pet #895
xapyb pet #895
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.
this was quite a lot of work! thanks
const NiftiImageData<dataType>& a = dynamic_cast<const NiftiImageData<dataType>&>(a_a); | ||
const NiftiImageData<dataType>& b = dynamic_cast<const NiftiImageData<dataType>&>(a_b); | ||
const NiftiImageData<dataType>& x = dynamic_cast<const NiftiImageData<dataType>&>(a_x); | ||
const NiftiImageData<dataType>& y = dynamic_cast<const NiftiImageData<dataType>&>(a_y); |
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 potentially throw unexpectedly if the type isn't ok. This is fine, but will confuse the user (certainly so a Python user).
should we cope with cases where the data-type isn't NiftiImageData
? Might be quite hard. But if we don't, I think we should put the whole thing in a try catch
block with some sensible error.
Also, in future, this can be shorter as
auto& a = dynamic_cast<const NiftiImageData<dataType>&>(a_a);
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.
At the python end sapyb
for vectors is in a try/except so it will default to python if there's an issue.
It does seem a bit strange restricting a and b to the same types, but I don't know how data is organised so whether a numpy array (for example) is compatible with nifty or stir arrays.
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. Nevertheless, it's the C++ library that should give sensible errors as much as we can, not the "client" Python/MATLAB
src/common/SIRF.py
Outdated
@@ -202,6 +202,8 @@ def add(self, other, out=None): | |||
return z | |||
def axpby(self, a, b, y, out=None, **kwargs): | |||
''' | |||
This function has been deprecated and will be removed in a future release. Please use `sapyb` instead. |
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.
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 happy to use this. But I'll need to add the Python-Deprecated
to the requirements, could you point out where these live?
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.
should be there already
https://github.com/SyneRBI/SIRF/blob/master/requirements.txt#L7
|
ok! |
400+ lines of code does seem a little excessive for basically some wrappers, but at least I understand SIRF a little now! |
src/common/SIRF.py
Outdated
tmp = self.multiply(a) | ||
y.multiply(b, out=z) | ||
z.add(tmp, out=z) |
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.
should better check the error message, and if it is "xapyb has not been implemented yet" then return NotImplemented, otherwise throw (something else happened)
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.
Frankly, I feel uneasy about your trying to cover lots of cases (axpby
, xapby
and essentially also axpyb
and xapby
+ self
variants) by one method - are all of them really needed? If they all are, I would rather have had several methods.
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.
besides, we normally try to do as little as possible in Python and Matlab interfaces, if only to reduce duplication
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.
axpby
previously covered vector and scalar methods, but with python computing the vector case, so I don't think it's covering more cases. But yes, it is a busy method.
In terms of the users passing a data-container to out
that is also one of the inputs, I guess we'd have to check on the ID to stop this, but as the operation is pixel-wise anyway I assumed it would be safe to allow. It doesn't change the implementation apart from the python code order avoids an intermediary step writing to out.
I think CIL currently wraps the C++ code with ctypes and passes the type of a and b as parameters. I guess this would be an option to simplify the python and matlab ends. but sapyb
needs to be consistent in behaviour across SIRF and CIL, I'm not sure we'd want to split it in to sapyb_vv
or sapyb_ss
at the python end as there's algorithms where a and b could be either.
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.
using input container as out
is ok - see e.g. __iadd__
.
I still believe unnecessary copies can be avoided, but let us leave this for now - after all, as I mentioned, in SIRF we try to do all computation in C++, so sapyb
will slim down eventually.
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 only unnecessary copy is when a
and b
are of different types, and the user has passed out
, as it will pre-calculate the vector * vector
side. Is this where you mean?
There is a specific case if the users passes y
and out
as the same object, where a
is a vector and b
a scalar. Then an intermediate step x.multiply(a, out=out)
would overwrite y
before it was used. So without checking on the datacontainer IDs it seems safer that where it has to calculate in steps it writes initially for a temporary container rather than out
. Of course if it was implemented in the C++ code it would be pixel-wise and not an issue.
Turns out we have a
I like it better that it has its own file though. I think |
@gfardell @evgueni-ovtchinnikov I have no clear feeling if this is feasible to merge in the next few days, or if we better postpone it (which would be fine). can you comment? |
I am updating it now and don't imagine it will take too long for it's current functionality, however if we want to delay it until the gadegtron xapyb is implemented I guess it would be more complete. |
@KrisThielemans I would postpone it - for one thing, I believe we should move the computation in Python |
I can't figure out why this stopped building. I can build and run the tests locally still. |
As the error is with recent changes in |
I've made a stab at the matlab wrappers but I haven't managed to get a license from SCD yet to run and test it. I've also not used matlab much so have no clue on error handling, when I get a license I'll be able to figure that out. |
tmp = x.same_object(); | ||
|
||
if a_scalar | ||
tmp = b.dot(y); |
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.
should be b.times(y)
, dot
computes scalar product
z.handle_ = calllib('msirf', 'mSIRF_axpby', ... | ||
ptr_a, x.handle_, 1.0, tmp.handle_); | ||
else | ||
tmp = a.dot(x); |
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.
as above
z.handle_ = calllib('msirf', 'mSIRF_axpby', ... | ||
ptr_a, x.handle_, ptr_b, y.handle_); |
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.
if neither a
nor b
is scalar, should call mSIRF_xapyb_vv
void* | ||
cSIRF_xapyb_ss( | ||
const void* ptr_x, const void* ptr_a, | ||
const void* ptr_y, const void* ptr_b | ||
) { | ||
try { | ||
DataContainer& x = | ||
objectFromHandle<DataContainer >(ptr_x); | ||
DataContainer& y = | ||
objectFromHandle<DataContainer >(ptr_y); | ||
void* h = x.new_data_container_handle(); | ||
DataContainer& z = objectFromHandle<DataContainer>(h); | ||
z.xapyb(x, ptr_a, y, ptr_b); | ||
return h; | ||
} | ||
CATCH; | ||
} | ||
|
||
extern "C" | ||
void* | ||
cSIRF_xapyb_vv( | ||
const void* ptr_x, const void* ptr_a, | ||
const void* ptr_y, const void* ptr_b | ||
) { | ||
try { | ||
DataContainer& x = | ||
objectFromHandle<DataContainer >(ptr_x); | ||
DataContainer& y = |
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.
these two functions have substantial overlap - why not have one cSIRF_xapyb
with extra const char* args
parameter that may have values "ss"
or "vv"
(and potentially other values, making it future proof)?
this would also solve lesser problem of breaking our naming scheme cSIRF_nameOfFunctionInCamelCase
void* cSIRF_xapyb_ss(const void* ptr_x, const PTR_FLOAT ptr_a, | ||
const void* ptr_y, const PTR_FLOAT ptr_b); | ||
void* cSIRF_xapyb_ss_Alt(const void* ptr_x, const PTR_FLOAT ptr_a, | ||
const void* ptr_y, const PTR_FLOAT ptr_b, void* ptr_z); | ||
void* cSIRF_xapyb_vv(const void* ptr_x, const void* ptr_a, | ||
const void* ptr_y, const void* ptr_b); | ||
void* cSIRF_xapyb_vv_Alt(const void* ptr_x, const void* ptr_a, | ||
const void* ptr_y, const void* ptr_b, void* ptr_z); |
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.
see the above suggestion to replace these four functions with two functions with an extra const char* args
parameter
merged via another branch |
I'm not sure if there's a way to handle this try/except better.