ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkIOTestHelper.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkIOTestHelper_h
19#define itkIOTestHelper_h
20#include "ITKIOImageBaseExport.h"
21#include <string>
22
23#include "itksys/SystemTools.hxx"
24#include "itkImageFileWriter.h"
25#include "itkImageFileReader.h"
26#include "itkRGBPixel.h"
27#include "itkVector.h"
28#include <cstdint>
29#include <limits>
30#include <random>
31#include <type_traits>
32namespace itk
33{
35{
36public:
37 template <typename TImage>
38 static typename TImage::Pointer
39 ReadImage(const std::string & fileName, const bool zeroOrigin = false, ImageIOBase::Pointer imageio = nullptr)
40 {
41 using ReaderType = itk::ImageFileReader<TImage>;
42
43 auto reader = ReaderType::New();
44 {
45 if (imageio)
46 {
47 reader->SetImageIO(imageio);
48 }
49 reader->SetFileName(fileName.c_str());
50 try
51 {
52 reader->Update();
53 }
54 catch (const itk::ExceptionObject & err)
55 {
56 std::cout << "Caught an exception: " << std::endl;
57 std::cout << err << ' ' << __FILE__ << ' ' << __LINE__ << std::endl;
58 throw;
59 }
60 catch (...)
61 {
62 std::cout << "Error while reading in image for patient " << fileName << std::endl;
63 throw;
64 }
65 }
66 typename TImage::Pointer image = reader->GetOutput();
67 if (zeroOrigin)
68 {
69 double origin[TImage::ImageDimension];
70 for (unsigned int i = 0; i < TImage::ImageDimension; ++i)
71 {
72 origin[i] = 0;
73 }
74 image->SetOrigin(origin);
75 }
76 return image;
77 }
78
79 template <typename ImageType, typename ImageIOType>
80 static void
81 WriteImage(typename ImageType::Pointer image,
82 const std::string & filename,
83 typename ImageIOType::Pointer imageio = nullptr)
84 {
85 const bool create_local_io_object{ imageio.IsNull() };
86 using WriterType = itk::ImageFileWriter<ImageType>;
87 { // Test valid filename writing
88 if (create_local_io_object)
89 {
90 imageio = ImageIOType::New();
91 }
92 auto writer = WriterType::New();
93 writer->SetImageIO(imageio);
94 writer->SetFileName(filename);
95 writer->SetInput(image);
96 try
97 {
98 writer->Update();
99 }
100 catch (const itk::ExceptionObject & err)
101 {
102 std::cerr << "Exception Object caught: " << std::endl << err << std::endl;
103 throw;
104 }
105 }
106
107 { // Test if writing to an invalid location causes exception to be thrown:
108 imageio = imageio->Clone(); // A new io object is needed because the HDF5 io object is single use. A new IO
109 // object is needed to re-initialize the internal state.
110
111 const std::string bad_root_path{ "/a_blatantly_obvious/bad_file_path/that/should/never/exist/on/the/computer/" };
112 const std::string bad_filename{ bad_root_path + filename };
113 bool exception_correctly_caught = false;
114
115 auto writer = WriterType::New();
116 writer->SetImageIO(imageio);
117 writer->SetFileName(bad_filename);
118 writer->SetInput(image);
119 try
120 {
121 writer->Update();
122 }
123 catch (const itk::ExceptionObject & /* err */)
124 {
125 // This is the correct behavior
126 std::cout << "Correctly caught exception for attempting to write to an invalid file." << std::endl;
127 exception_correctly_caught = true;
128 }
129 catch (...)
130 {
131 itkGenericExceptionMacro("IO library exception not converted to an itk::ExceptionObject.");
132 }
133 if (!exception_correctly_caught)
134 {
135 itkGenericExceptionMacro("Invalid file writing path did not throw an exception: " << bad_filename << " with "
136 << imageio->GetNameOfClass());
137 }
138 }
139 }
140
141 // Sample a value of arithmetic type T uniformly in [0, bound], avoiding
142 // implementation-defined narrowing and the high-bits-zero artifact that
143 // a single 32-bit engine() output produces for 64-bit integral types.
144 template <typename T>
145 static T
146 BoundedRandom(std::mt19937 & randomNumberEngine, T bound)
147 {
148 static_assert(std::is_arithmetic_v<T>, "BoundedRandom: T must be arithmetic");
149 if constexpr (std::is_floating_point_v<T>)
150 {
151 std::uniform_real_distribution<T> dist{ static_cast<T>(0), bound };
152 return dist(randomNumberEngine);
153 }
154 else
155 {
156 using U = std::make_unsigned_t<T>;
157 U raw;
158 if constexpr (sizeof(T) > sizeof(std::mt19937::result_type))
159 {
160 // Combine two 32-bit engine outputs to fill the high bits of 64-bit pixel types.
161 raw = (static_cast<U>(randomNumberEngine()) << 32) | static_cast<U>(randomNumberEngine());
162 }
163 else
164 {
165 raw = static_cast<U>(randomNumberEngine());
166 }
167 const U bound_u = static_cast<U>(bound);
168 // No bound to apply when bound saturates U; bound_u + 1 would wrap to 0
169 // and raw % 0 traps with SIGFPE.
170 if (bound_u == std::numeric_limits<U>::max())
171 {
172 return static_cast<T>(raw);
173 }
174 return static_cast<T>(raw % (bound_u + U{ 1 }));
175 }
176 }
177
178 template <typename TPixel>
179 static void
180 RandomPix(std::mt19937 & randomNumberEngine,
181 TPixel & pix,
182 double _max = static_cast<double>(itk::NumericTraits<TPixel>::max()))
183 {
184 static_assert(std::is_arithmetic_v<TPixel>, "RandomPix: TPixel must be arithmetic");
185 pix = BoundedRandom<TPixel>(randomNumberEngine, static_cast<TPixel>(_max));
186 }
187
188 template <typename T>
189 static void
190 RandomPix(std::mt19937 & randomNumberEngine,
191 itk::RGBPixel<T> & pix,
192 double _max = static_cast<double>(itk::NumericTraits<T>::max()))
193 {
194 for (unsigned int i = 0; i < 3; ++i)
195 {
196 pix[i] = BoundedRandom<T>(randomNumberEngine, static_cast<T>(_max));
197 }
198 }
199
200 template <typename T, unsigned int VLength>
201 static void
202 RandomPix(std::mt19937 & randomNumberEngine,
204 double _max = static_cast<double>(itk::NumericTraits<T>::max()))
205 {
206 for (unsigned int i = 0; i < VLength; ++i)
207 {
208 pix[i] = BoundedRandom<T>(randomNumberEngine, static_cast<T>(_max));
209 }
210 }
211
212 static int
213 Remove(const char * fname)
214 {
215 return static_cast<bool>(itksys::SystemTools::RemoveFile(fname));
216 }
217
218 template <typename ImageType>
219 static void
220 SetIdentityDirection(typename ImageType::Pointer & im)
221 {
222 typename ImageType::DirectionType dir;
223 dir.SetIdentity();
224 im->SetDirection(dir);
225 }
226
227 template <typename ImageType>
228 static typename ImageType::Pointer
229 AllocateImageFromRegionAndSpacing(const typename ImageType::RegionType & region,
230 const typename ImageType::SpacingType & spacing)
231 {
232 auto rval = ImageType::New();
234 rval->SetSpacing(spacing);
235 rval->SetRegions(region);
236 rval->Allocate();
237 return rval;
238 }
239 template <typename ImageType>
240 static typename ImageType::Pointer
241 AllocateImageFromRegionAndSpacing(const typename ImageType::RegionType & region,
242 const typename ImageType::SpacingType & spacing,
243 int vecLength)
244 {
245 auto rval = ImageType::New();
246 rval->SetSpacing(spacing);
247 rval->SetRegions(region);
248 rval->SetVectorLength(vecLength);
249 rval->Allocate();
250 return rval;
251 }
252};
253} // namespace itk
254#endif // itkIOTestHelper_h
Standard exception handling object.
static ImageType::Pointer AllocateImageFromRegionAndSpacing(const typename ImageType::RegionType &region, const typename ImageType::SpacingType &spacing)
static void SetIdentityDirection(typename ImageType::Pointer &im)
static ImageType::Pointer AllocateImageFromRegionAndSpacing(const typename ImageType::RegionType &region, const typename ImageType::SpacingType &spacing, int vecLength)
static void RandomPix(std::mt19937 &randomNumberEngine, itk::Vector< T, VLength > &pix, double _max=static_cast< double >(itk::NumericTraits< T >::max()))
static int Remove(const char *fname)
static TImage::Pointer ReadImage(const std::string &fileName, const bool zeroOrigin=false, ImageIOBase::Pointer imageio=nullptr)
static T BoundedRandom(std::mt19937 &randomNumberEngine, T bound)
static void RandomPix(std::mt19937 &randomNumberEngine, TPixel &pix, double _max=static_cast< double >(itk::NumericTraits< TPixel >::max()))
static void WriteImage(typename ImageType::Pointer image, const std::string &filename, typename ImageIOType::Pointer imageio=nullptr)
static void RandomPix(std::mt19937 &randomNumberEngine, itk::RGBPixel< T > &pix, double _max=static_cast< double >(itk::NumericTraits< T >::max()))
Data source that reads image data from a single file.
Writes image data to a single file.
SmartPointer< Self > Pointer
static constexpr T max(const T &)
Represent Red, Green and Blue components for color images.
Definition itkRGBPixel.h:58
A templated class holding a n-Dimensional vector.
Definition itkVector.h:63
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....