Skip to content

Commit

Permalink
implemented safer C++ data type handling, fixes #1193
Browse files Browse the repository at this point in the history
  • Loading branch information
evgueni-ovtchinnikov committed May 26, 2023
1 parent 8ea4cac commit 4dfdcba
Show file tree
Hide file tree
Showing 34 changed files with 1,397 additions and 988 deletions.
2 changes: 1 addition & 1 deletion src/Registration/cReg/NiftiBasedRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ limitations under the License.
using namespace sirf;

template<class dataType>
void NiftiBasedRegistration<dataType>::convert_to_NiftiImageData_if_not_already(std::shared_ptr<const NiftiImageData3D<dataType> > &output_sptr, const std::shared_ptr<const ImageData> &input_sptr)
void NiftiBasedRegistration<dataType>::convert_to_NiftiImageData_if_not_already(std::shared_ptr<const NiftiImageData3D<dataType> > &output_sptr, const std::shared_ptr<const ImageData<dataType> > &input_sptr)
{
// Try to dynamic cast from ImageData to (const) NiftiImageData. This will only succeed if original type was NiftiImageData
output_sptr = std::dynamic_pointer_cast<const NiftiImageData3D<dataType> >(input_sptr);
Expand Down
71 changes: 39 additions & 32 deletions src/Registration/cReg/NiftiImageData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,24 @@ static void check_folder_exists_if_not_create(const std::string &path)
template<class dataType>
NiftiImageData<dataType>::NiftiImageData(const NiftiImageData<dataType>& to_copy)
{
*this = dynamic_cast<const ImageData&>(to_copy);
*this = dynamic_cast<const ImageData<dataType>&>(to_copy);
}

template<class dataType>
NiftiImageData<dataType>& NiftiImageData<dataType>::operator=(const NiftiImageData<dataType>& to_copy)
{
*this = dynamic_cast<const ImageData&>(to_copy);
*this = dynamic_cast<const ImageData<dataType>&>(to_copy);
return *this;
}

template<class dataType>
NiftiImageData<dataType>::NiftiImageData(const ImageData& to_copy)
NiftiImageData<dataType>::NiftiImageData(const ImageData<dataType>& to_copy)
{
*this = to_copy;
}

template<class dataType>
NiftiImageData<dataType>& NiftiImageData<dataType>::operator=(const ImageData& to_copy)
NiftiImageData<dataType>& NiftiImageData<dataType>::operator=(const ImageData<dataType>& to_copy)
{
// Check for self-assignment
if (this != &to_copy) {
Expand Down Expand Up @@ -213,10 +213,11 @@ std::shared_ptr<nifti_image> NiftiImageData<dataType>::create_from_geom_info(con
}

template<class dataType>
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_real_component(std::shared_ptr<NiftiImageData> &out_sptr, const std::shared_ptr<const ImageData> in_sptr)
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_real_component(std::shared_ptr<NiftiImageData>& out_sptr, const std::shared_ptr<const DataContainer> dc_sptr)
{
auto in_sptr = std::dynamic_pointer_cast<const ImageData<complex_float_t> >(dc_sptr);
// Create image from input
out_sptr = std::make_shared<NiftiImageData<dataType> >(*in_sptr);
out_sptr = std::make_shared<NiftiImageData<dataType> >(*dc_sptr);

auto &it_in = in_sptr->begin();
auto &it_out = out_sptr->begin();
Expand All @@ -225,13 +226,14 @@ void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_real_com
}

template<class dataType>
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_imag_component(std::shared_ptr<NiftiImageData> &out_sptr, const std::shared_ptr<const ImageData> in_sptr)
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_imag_component(std::shared_ptr<NiftiImageData>& out_sptr, const std::shared_ptr<const DataContainer> dc_sptr)
{
auto in_sptr = std::dynamic_pointer_cast<const ImageData<complex_float_t> >(dc_sptr);
if (!in_sptr->is_complex())
std::cout << "\nNiftiImageData<dataType>::construct_NiftiImageData_from_complex_im. Warning, input image is not complex. Complex component will be empty\n";

// Create image from input
out_sptr = std::make_shared<NiftiImageData<dataType> >(*in_sptr);
out_sptr = std::make_shared<NiftiImageData<dataType> >(*dc_sptr);

auto &it_in = in_sptr->begin();
auto &it_out = out_sptr->begin();
Expand All @@ -240,7 +242,7 @@ void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im_imag_com
}

template<class dataType>
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im(std::shared_ptr<NiftiImageData> &out_real_sptr, std::shared_ptr<NiftiImageData> &out_imag_sptr, const std::shared_ptr<const ImageData> in_sptr)
void NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im(std::shared_ptr<NiftiImageData> &out_real_sptr, std::shared_ptr<NiftiImageData> &out_imag_sptr, const std::shared_ptr<const DataContainer> in_sptr)
{
construct_NiftiImageData_from_complex_im_real_component(out_real_sptr,in_sptr);
construct_NiftiImageData_from_complex_im_imag_component(out_imag_sptr,in_sptr);
Expand Down Expand Up @@ -1670,10 +1672,11 @@ dataType
NiftiImageData<dataType>::
get_inner_product(const NiftiImageData &other) const
{
dataType s;
this->dot(other, &s);
return s;
// return std::inner_product(this->begin(),this->end(),other.begin(),dataType(0));
return (dataType)this->dot(other);
// dataType s;
// this->dot(other, &s);
// return s;
//// return std::inner_product(this->begin(),this->end(),other.begin(),dataType(0));
}

template<class dataType>
Expand Down Expand Up @@ -1738,38 +1741,42 @@ bool NiftiImageData<dataType>::are_equal_to_given_accuracy(const NiftiImageData
// Pure virtual methods from ImageData
// ------------------------------------------------------------------------------ //
template<class dataType>
void NiftiImageData<dataType>::dot(const DataContainer& a_x, void* ptr) const
float
NiftiImageData<dataType>::dot(const DataContainer& a_x) const
{
const NiftiImageData<dataType>& x = dynamic_cast<const NiftiImageData<dataType>&>(a_x);
ASSERT(_nifti_image->nvox == x._nifti_image->nvox, "dot operands size mismatch");
double s = 0.0;
for (unsigned i = 0; i < this->_nifti_image->nvox; ++i)
s += double(_data[i]) * x._data[i];
float* ptr_s = static_cast<float*>(ptr);
*ptr_s = (float)s;
return (float)s;
//float* ptr_s = static_cast<float*>(ptr);
//*ptr_s = (float)s;
}

template<class dataType>
void NiftiImageData<dataType>::sum(void* ptr) const
float NiftiImageData<dataType>::sum() const
{
double s = 0.0;
for (unsigned i = 0; i < this->_nifti_image->nvox; ++i)
s += _data[i];
float* ptr_s = static_cast<float*>(ptr);
*ptr_s = (float)s;
return (float)s;
//float* ptr_s = static_cast<float*>(ptr);
//*ptr_s = (float)s;
}

template<class dataType>
void NiftiImageData<dataType>::max(void* ptr) const
float NiftiImageData<dataType>::max() const
{
float s = 0.0;
for (unsigned i = 0; i < this->_nifti_image->nvox; ++i) {
float si = _data[i];
if (si > s)
s = si;
}
float* ptr_s = static_cast<float*>(ptr);
*ptr_s = s;
return s;
//float* ptr_s = static_cast<float*>(ptr);
//*ptr_s = s;
}

template<class dataType>
Expand Down Expand Up @@ -1919,56 +1926,56 @@ template<class dataType>
void NiftiImageData<dataType>::multiply
(const DataContainer& a_x, const DataContainer& a_y)
{
binary_op(a_x, a_y, DataContainer::product<dataType>);
binary_op(a_x, a_y, DataContainerTempl<float>::product);
}

template<class dataType>
void NiftiImageData<dataType>::multiply
(const DataContainer& a_x, const void* a_y)
{
semibinary_op(a_x, a_y, DataContainer::product<dataType>);
semibinary_op(a_x, a_y, DataContainerTempl<float>::product);
}

template<class dataType>
void NiftiImageData<dataType>::add
(const DataContainer& a_x, const void* a_y)
{
semibinary_op(a_x, a_y, DataContainer::sum<dataType>);
semibinary_op(a_x, a_y, DataContainerTempl<float>::sum);
}

template<class dataType>
void NiftiImageData<dataType>::divide
(const DataContainer& a_x, const DataContainer& a_y)
{
binary_op(a_x, a_y, DataContainer::ratio<dataType>);
binary_op(a_x, a_y, DataContainerTempl<float>::ratio);
}

template<class dataType>
void NiftiImageData<dataType>::maximum
(const DataContainer& a_x, const DataContainer& a_y)
{
binary_op(a_x, a_y, DataContainer::maximum<dataType>);
binary_op(a_x, a_y, DataContainerTempl<float>::maximum);
}

template<class dataType>
void NiftiImageData<dataType>::maximum
(const DataContainer& a_x, const void* a_y)
{
semibinary_op(a_x, a_y, DataContainer::maximum<dataType>);
semibinary_op(a_x, a_y, DataContainerTempl<float>::maximum);
}

template<class dataType>
void NiftiImageData<dataType>::minimum
(const DataContainer& a_x, const DataContainer& a_y)
{
binary_op(a_x, a_y, DataContainer::minimum<dataType>);
binary_op(a_x, a_y, DataContainerTempl<float>::minimum);
}

template<class dataType>
void NiftiImageData<dataType>::minimum
(const DataContainer& a_x, const void* a_y)
{
semibinary_op(a_x, a_y, DataContainer::minimum<dataType>);
semibinary_op(a_x, a_y, DataContainerTempl<float>::minimum);
}

template<class dataType>
Expand Down Expand Up @@ -2006,13 +2013,13 @@ void NiftiImageData<dataType>::sqrt(const DataContainer& a_x)
template<class dataType>
void NiftiImageData<dataType>::sign(const DataContainer& a_x)
{
unary_op(a_x, DataContainer::sign);
unary_op(a_x, DataContainerTempl<float>::sign);
}

template<class dataType>
void NiftiImageData<dataType>::abs(const DataContainer& a_x)
{
unary_op(a_x, DataContainer::abs);
unary_op(a_x, DataContainerTempl<float>::abs);
}

template<class dataType>
Expand Down
4 changes: 2 additions & 2 deletions src/Registration/cReg/NiftiImageData3DTensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ tensor_component_maths(
template<class dataType>
void NiftiImageData3DTensor<dataType>::
multiply_tensor_component
(const int dim, const std::shared_ptr<const ImageData> &scalar_im_sptr)
(const int dim, const std::shared_ptr<const ImageData<dataType> > &scalar_im_sptr)
{
this->tensor_component_maths(dim, scalar_im_sptr, NiftiImageData<dataType>::mul);
}
Expand All @@ -227,7 +227,7 @@ multiply_tensor_component
template<class dataType>
void NiftiImageData3DTensor<dataType>::
add_to_tensor_component
(const int dim, const std::shared_ptr<const ImageData> &scalar_im_sptr)
(const int dim, const std::shared_ptr<const ImageData<dataType> > &scalar_im_sptr)
{
this->tensor_component_maths(dim, scalar_im_sptr, NiftiImageData<dataType>::ADD);
}
Expand Down
24 changes: 13 additions & 11 deletions src/Registration/cReg/NiftyResampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,19 @@ using namespace sirf;
using namespace detail;

template<class dataType>
static void convert_ImageData_to_ComplexNiftiImageData(ComplexNiftiImageData<dataType> &output, const std::shared_ptr<const ImageData> input_sptr)
static void convert_ImageData_to_ComplexNiftiImageData(ComplexNiftiImageData<dataType> &output, const std::shared_ptr<const DataContainer> input_sptr)
{
// if input is real, only convert first bit
if (!input_sptr->is_complex()) {
output.real() = std::make_shared<NiftiImageData<dataType> >(*input_sptr);
output.real() = std::make_shared<NiftiImageData<dataType> > //(*input_sptr);
(*std::dynamic_pointer_cast<const ImageData<float> >(input_sptr));
output.imag().reset();
}
// if input is complex, only set both
else {
std::shared_ptr<NiftiImageData<dataType> > &output_real = output.real();
std::shared_ptr<NiftiImageData<dataType> > &output_imag = output.imag();
NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im(output_real,output_imag,input_sptr);
NiftiImageData<dataType>::construct_NiftiImageData_from_complex_im(output_real, output_imag, input_sptr);
}
}

Expand Down Expand Up @@ -228,8 +229,9 @@ static void check_images_match(
}

template<class dataType>
static void set_post_resample_outputs(std::shared_ptr<ImageData> &output_to_return_sptr, std::shared_ptr<ImageData> &output_as_member_sptr, const ComplexNiftiImageData<dataType> resampled_niftis)
static void set_post_resample_outputs(std::shared_ptr<DataContainer> &out_to_return_sptr, std::shared_ptr<DataContainer> &output_as_member_sptr, const ComplexNiftiImageData<dataType> resampled_niftis)
{
std::shared_ptr<ImageData<dataType> > output_to_return_sptr = std::dynamic_pointer_cast<ImageData<dataType> >(out_to_return_sptr);
// If output is only real, set that
if (!output_to_return_sptr->is_complex())
output_to_return_sptr->fill(*resampled_niftis.real());
Expand All @@ -238,7 +240,7 @@ static void set_post_resample_outputs(std::shared_ptr<ImageData> &output_to_retu
NumberType::Type output_num_type = (*output_to_return_sptr->begin()).get_typeID();
if (output_num_type != NumberType::CXFLOAT)
throw std::runtime_error("NiftyResampler: Only complex type currently supported is complex float");
ImageData::Iterator &it_out = output_to_return_sptr->begin();
ImageData<dataType> ::Iterator &it_out = output_to_return_sptr->begin();
auto &it_real = resampled_niftis.real()->begin();
auto &it_imag = resampled_niftis.imag()->begin();
for (; it_out!=output_to_return_sptr->end(); ++it_real, ++it_imag, ++it_out) {
Expand All @@ -252,19 +254,19 @@ static void set_post_resample_outputs(std::shared_ptr<ImageData> &output_to_retu
}

template<class dataType>
std::shared_ptr<ImageData> NiftyResampler<dataType>::forward(const std::shared_ptr<const ImageData> input_sptr)
std::shared_ptr<DataContainer> NiftyResampler<dataType>::forward(const std::shared_ptr<const DataContainer> input_sptr)
{
// Call the set up
set_up_forward();

std::shared_ptr<ImageData> output_sptr = this->_reference_image_sptr->clone();
std::shared_ptr<DataContainer> output_sptr = this->_reference_image_sptr->clone();
forward(output_sptr, input_sptr);

return output_sptr;
}

template<class dataType>
void NiftyResampler<dataType>::forward(std::shared_ptr<ImageData> output_sptr, const std::shared_ptr<const ImageData> input_sptr)
void NiftyResampler<dataType>::forward(std::shared_ptr<DataContainer> output_sptr, const std::shared_ptr<const DataContainer> input_sptr)
{
// Call the set up
set_up_forward();
Expand Down Expand Up @@ -295,19 +297,19 @@ void NiftyResampler<dataType>::forward(std::shared_ptr<ImageData> output_sptr, c
}

template<class dataType>
std::shared_ptr<ImageData> NiftyResampler<dataType>::adjoint(const std::shared_ptr<const ImageData> input_sptr)
std::shared_ptr<DataContainer> NiftyResampler<dataType>::adjoint(const std::shared_ptr<const DataContainer> input_sptr)
{
// Call the set up
set_up_adjoint();

std::shared_ptr<ImageData> output_sptr = this->_floating_image_sptr->clone();
std::shared_ptr<DataContainer> output_sptr = this->_floating_image_sptr->clone();
adjoint(output_sptr, input_sptr);

return output_sptr;
}

template<class dataType>
void NiftyResampler<dataType>::adjoint(std::shared_ptr<ImageData> output_sptr, const std::shared_ptr<const ImageData> input_sptr)
void NiftyResampler<dataType>::adjoint(std::shared_ptr<DataContainer> output_sptr, const std::shared_ptr<const DataContainer> input_sptr)
{
// Call the set up
set_up_adjoint();
Expand Down
6 changes: 3 additions & 3 deletions src/Registration/cReg/Registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ limitations under the License.
using namespace sirf;

template<class dataType>
void Registration<dataType>::set_reference_image(const std::shared_ptr<const ImageData> reference_image_sptr)
void Registration<dataType>::set_reference_image(const std::shared_ptr<const ImageData<dataType> > reference_image_sptr)
{
_reference_image_sptr = reference_image_sptr;
_reference_image_filename = "";
}

template<class dataType>
void Registration<dataType>::set_floating_image(const std::shared_ptr<const ImageData> floating_image_sptr)
void Registration<dataType>::set_floating_image(const std::shared_ptr<const ImageData<dataType> > floating_image_sptr)
{
if (!_floating_image_filenames.empty()) {
std::cout << "\nClearing floating images set via filename";
Expand All @@ -53,7 +53,7 @@ void Registration<dataType>::set_floating_image(const std::shared_ptr<const Imag
}

template<class dataType>
void Registration<dataType>::add_floating_image(const std::shared_ptr<const ImageData> floating_image_sptr)
void Registration<dataType>::add_floating_image(const std::shared_ptr<const ImageData<dataType> > floating_image_sptr)
{
if (!_floating_image_filenames.empty()) {
std::cout << "\nClearing floating images set via filename";
Expand Down
8 changes: 4 additions & 4 deletions src/Registration/cReg/Resample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ using namespace sirf;

/// Set reference image
template<class dataType>
void Resampler<dataType>::set_reference_image(const std::shared_ptr<const ImageData> reference_image_sptr)
void Resampler<dataType>::set_reference_image(const std::shared_ptr<const DataContainer> reference_image_sptr)
{
_reference_image_sptr = reference_image_sptr;
_need_to_set_up = true;
Expand All @@ -43,7 +43,7 @@ void Resampler<dataType>::set_reference_image(const std::shared_ptr<const ImageD

/// Set floating image
template<class dataType>
void Resampler<dataType>::set_floating_image(const std::shared_ptr<const ImageData> floating_image_sptr)
void Resampler<dataType>::set_floating_image(const std::shared_ptr<const DataContainer > floating_image_sptr)
{
_floating_image_sptr = floating_image_sptr;
_need_to_set_up = true;
Expand Down Expand Up @@ -82,13 +82,13 @@ void Resampler<dataType>::check_parameters()
}

template<class dataType>
std::shared_ptr<ImageData> Resampler<dataType>::backward(const std::shared_ptr<const ImageData> input_sptr)
std::shared_ptr<DataContainer > Resampler<dataType>::backward(const std::shared_ptr<const DataContainer > input_sptr)
{
return adjoint(input_sptr);
}

template<class dataType>
void Resampler<dataType>::backward(std::shared_ptr<ImageData> output_sptr, const std::shared_ptr<const ImageData> input_sptr)
void Resampler<dataType>::backward(std::shared_ptr<DataContainer > output_sptr, const std::shared_ptr<const DataContainer > input_sptr)
{
adjoint(output_sptr, input_sptr);
}
Expand Down
Loading

0 comments on commit 4dfdcba

Please sign in to comment.