Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkImageAccessorTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "itkBarrier.h"
14 #include "mitkIOUtil.h"
15 #include "mitkImage.h"
18 #include "mitkImageReadAccessor.h"
19 #include "mitkImageTimeSelector.h"
20 #include "mitkImageWriteAccessor.h"
21 #include <fstream>
22 #include <itkMultiThreader.h>
23 #include <itksys/SystemTools.hxx>
24 #include <mitkTestingMacros.h>
25 #include <cstdlib>
26 #include <ctime>
27 
28 struct ThreadData
29 {
30  itk::Barrier::Pointer m_Barrier; // holds a pointer to the used barrier
31  mitk::Image::Pointer data; // some random data
32  int m_NoOfThreads; // holds the number of generated threads
33  bool m_Successful; // to check if everything worked
34 };
35 
36 itk::SimpleFastMutexLock testMutex;
37 
38 ITK_THREAD_RETURN_TYPE ThreadMethod(void *data)
39 {
40  /* extract data pointer from Thread Info structure */
41  auto *pInfo = (struct itk::MultiThreader::ThreadInfoStruct *)data;
42 
43  // some data validity checking
44  if (pInfo == nullptr)
45  {
46  return ITK_THREAD_RETURN_VALUE;
47  }
48  if (pInfo->UserData == nullptr)
49  {
50  return ITK_THREAD_RETURN_VALUE;
51  }
52 
53  // obtain user data for processing
54  auto *threadData = (ThreadData *)pInfo->UserData;
55 
56  srand(pInfo->ThreadID);
57 
58  mitk::Image::Pointer im = threadData->data;
59 
60  int nrSlices = im->GetDimension(2);
61 
62  // Create randomly a PixelRead- or PixelWriteAccessor for a slice and access all pixels in it.
63  try
64  {
65  if (rand() % 2)
66  {
67  testMutex.Lock();
68  mitk::ImageDataItem *iDi = im->GetSliceData(rand() % nrSlices);
69  testMutex.Unlock();
70  while (!iDi->IsComplete())
71  {
72  }
73 
74  // MITK_INFO << "pixeltype: " << im->GetPixelType().GetComponentTypeAsString();
75 
76  if ((im->GetPixelType().GetComponentTypeAsString() == "short") && (im->GetDimension() == 3))
77  {
78  // Use pixeltype&dimension specific read accessor
79 
80  int xlength = im->GetDimension(0);
81  int ylength = im->GetDimension(1);
82 
83  mitk::ImagePixelReadAccessor<short, 2> readAccessor(im, iDi);
84 
85  itk::Index<2> idx;
86  for (int i = 0; i < xlength; ++i)
87  {
88  for (int j = 0; j < ylength; ++j)
89  {
90  idx[0] = i;
91  idx[1] = j;
92  readAccessor.GetPixelByIndexSafe(idx);
93  }
94  }
95  }
96  else
97  {
98  // use general accessor
100  delete iRA;
101  }
102  }
103  else
104  {
105  testMutex.Lock();
106  mitk::ImageDataItem *iDi = im->GetSliceData(rand() % nrSlices);
107  testMutex.Unlock();
108  while (!iDi->IsComplete())
109  {
110  }
111 
112  if ((im->GetPixelType().GetComponentTypeAsString() == "short") && (im->GetDimension() == 3))
113  {
114  // Use pixeltype&dimension specific read accessor
115 
116  int xlength = im->GetDimension(0);
117  int ylength = im->GetDimension(1);
118 
119  mitk::ImagePixelWriteAccessor<short, 2> writeAccessor(im, iDi);
120 
121  itk::Index<2> idx;
122  for (int i = 0; i < xlength; ++i)
123  {
124  for (int j = 0; j < ylength; ++j)
125  {
126  idx[0] = i;
127  idx[1] = j;
128  short newVal = rand() % 16000;
129  writeAccessor.SetPixelByIndexSafe(idx, newVal);
130  short val = writeAccessor.GetPixelByIndexSafe(idx);
131  if (val != newVal)
132  {
133  threadData->m_Successful = false;
134  }
135  }
136  }
137  }
138  else
139  {
140  // use general accessor
141  mitk::ImageWriteAccessor iB(im, iDi);
142  void *pointer = iB.GetData();
143  *((char *)pointer) = 0;
144  }
145  }
146  }
147  catch ( const mitk::MemoryIsLockedException &e )
148  {
149  threadData->m_Successful = false;
150  e.Print(std::cout);
151  }
152  catch ( const mitk::Exception &e )
153  {
154  threadData->m_Successful = false;
155  e.Print(std::cout);
156  }
157 
158  // data processing end!
159  threadData->m_Barrier->Wait();
160  return ITK_THREAD_RETURN_VALUE;
161 }
162 
163 int mitkImageAccessorTest(int argc, char *argv[])
164 {
165  MITK_TEST_BEGIN("mitkImageAccessorTest");
166 
167  std::cout << "Loading file: ";
168  if (argc == 0)
169  {
170  std::cout << "no file specified [FAILED]" << std::endl;
171  return EXIT_FAILURE;
172  }
173  mitk::Image::Pointer image = nullptr;
174  try
175  {
176  image = mitk::IOUtil::Load<mitk::Image>(std::string(argv[1]));
177 
178  if (image.IsNull())
179  {
180  MITK_TEST_FAILED_MSG(<< "file could not be loaded [FAILED]")
181  }
182  }
183  catch ( const itk::ExceptionObject &ex )
184  {
185  MITK_TEST_FAILED_MSG(<< "Exception: " << ex.GetDescription() << "[FAILED]")
186  }
187 
188  // CHECK INAPPROPRIATE AND SPECIAL USAGE
189 
190  // recursive mutex lock
191  MITK_TEST_OUTPUT(<< "Testing a recursive mutex lock attempt, should end in an exception ...");
192 
194  mitk::ImageWriteAccessor first(image);
195  mitk::ImageReadAccessor second(image);
197 
198  // ignore lock mechanism in read accessor
199  try
200  {
201  mitk::ImageWriteAccessor first(image);
203  MITK_TEST_CONDITION_REQUIRED(true, "Testing the option flag \"IgnoreLock\" in ReadAccessor");
204  }
205  catch (const mitk::Exception & /*e*/)
206  {
207  MITK_TEST_CONDITION_REQUIRED(false, "Ignoring the lock mechanism leads to exception.");
208  }
209 
210  // CREATE THREADS
211 
212  image->GetGeometry()->Initialize();
213 
214  itk::MultiThreader::Pointer threader = itk::MultiThreader::New();
215  unsigned int noOfThreads = 100;
216 
217  // initialize barrier
218  itk::Barrier::Pointer barrier = itk::Barrier::New();
219  barrier->Initialize(noOfThreads + 1); // add one for we stop the base thread when the worker threads are processing
220 
221  auto *threadData = new ThreadData;
222  threadData->m_Barrier = barrier;
223  threadData->m_NoOfThreads = noOfThreads;
224  threadData->data = image;
225  threadData->m_Successful = true;
226 
227  // spawn threads
228  for (unsigned int i = 0; i < noOfThreads; ++i)
229  {
230  threader->SpawnThread(ThreadMethod, threadData);
231  }
232  // stop the base thread during worker thread execution
233  barrier->Wait();
234 
235  // terminate threads
236  for (unsigned int j = 0; j < noOfThreads; ++j)
237  {
238  threader->TerminateThread(j);
239  }
240 
241  bool TestSuccessful = threadData->m_Successful;
242  delete threadData;
243 
244  MITK_TEST_CONDITION_REQUIRED(TestSuccessful, "Testing image access from multiple threads");
245 
246  MITK_TEST_END();
247 }
const TPixel & GetPixelByIndexSafe(const itk::Index< VDimension > &idx) const
Gives locked and index-based write access for a particular image part. The class provides several set...
itk::SimpleFastMutexLock testMutex
#define MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS)
Gives locked and index-based read access for a particular image part. The class provides several set-...
void SetPixelByIndexSafe(const itk::Index< VDimension > &idx, const TPixel &value)
#define MITK_TEST_CONDITION_REQUIRED(COND, MSG)
ITK_THREAD_RETURN_TYPE ThreadMethod(void *data)
section GeneralTestsDeprecatedOldTestingStyle Deprecated macros All tests with MITK_TEST_BEGIN()
void * GetData()
Gives full data access.
const TPixel & GetPixelByIndexSafe(const itk::Index< VDimension > &idx) const
#define MITK_TEST_OUTPUT(x)
Output some text.
An object of this class represents an exception of MITK. Please don&#39;t instantiate exceptions manually...
Definition: mitkException.h:45
#define MITK_TEST_FAILED_MSG(MSG)
Fail and finish test with message MSG.
#define MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS)
Begin block which should be checked for exceptions.
mitk::Image::Pointer image
int mitkImageAccessorTest(int argc, char *argv[])
ImageWriteAccessor class to get locked write-access for a particular image part.
Internal class for managing references on sub-images.
and MITK_TEST_END()
ImageReadAccessor class to get locked read access for a particular image part.