Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "itkBarrier.h"
18 #include "mitkIOUtil.h"
19 #include "mitkImage.h"
22 #include "mitkImageReadAccessor.h"
23 #include "mitkImageTimeSelector.h"
24 #include "mitkImageWriteAccessor.h"
25 #include <fstream>
26 #include <itkMultiThreader.h>
27 #include <itksys/SystemTools.hxx>
28 #include <mitkTestingMacros.h>
29 #include <stdlib.h>
30 #include <time.h>
31 
32 struct ThreadData
33 {
34  itk::Barrier::Pointer m_Barrier; // holds a pointer to the used barrier
35  mitk::Image::Pointer data; // some random data
36  int m_NoOfThreads; // holds the number of generated threads
37  bool m_Successful; // to check if everything worked
38 };
39 
40 itk::SimpleFastMutexLock testMutex;
41 
42 ITK_THREAD_RETURN_TYPE ThreadMethod(void *data)
43 {
44  /* extract data pointer from Thread Info structure */
45  struct itk::MultiThreader::ThreadInfoStruct *pInfo = (struct itk::MultiThreader::ThreadInfoStruct *)data;
46 
47  // some data validity checking
48  if (pInfo == NULL)
49  {
50  return ITK_THREAD_RETURN_VALUE;
51  }
52  if (pInfo->UserData == NULL)
53  {
54  return ITK_THREAD_RETURN_VALUE;
55  }
56 
57  // obtain user data for processing
58  ThreadData *threadData = (ThreadData *)pInfo->UserData;
59 
60  srand(pInfo->ThreadID);
61 
62  mitk::Image::Pointer im = threadData->data;
63 
64  int nrSlices = im->GetDimension(2);
65 
66  // Create randomly a PixelRead- or PixelWriteAccessor for a slice and access all pixels in it.
67  try
68  {
69  if (rand() % 2)
70  {
71  testMutex.Lock();
72  mitk::ImageDataItem *iDi = im->GetSliceData(rand() % nrSlices);
73  testMutex.Unlock();
74  while (!iDi->IsComplete())
75  {
76  }
77 
78  // MITK_INFO << "pixeltype: " << im->GetPixelType().GetComponentTypeAsString();
79 
80  if ((im->GetPixelType().GetComponentTypeAsString() == "short") && (im->GetDimension() == 3))
81  {
82  // Use pixeltype&dimension specific read accessor
83 
84  int xlength = im->GetDimension(0);
85  int ylength = im->GetDimension(1);
86 
87  mitk::ImagePixelReadAccessor<short, 2> readAccessor(im, iDi);
88 
89  itk::Index<2> idx;
90  for (int i = 0; i < xlength; ++i)
91  {
92  for (int j = 0; j < ylength; ++j)
93  {
94  idx[0] = i;
95  idx[1] = j;
96  readAccessor.GetPixelByIndexSafe(idx);
97  }
98  }
99  }
100  else
101  {
102  // use general accessor
104  delete iRA;
105  }
106  }
107  else
108  {
109  testMutex.Lock();
110  mitk::ImageDataItem *iDi = im->GetSliceData(rand() % nrSlices);
111  testMutex.Unlock();
112  while (!iDi->IsComplete())
113  {
114  }
115 
116  if ((im->GetPixelType().GetComponentTypeAsString() == "short") && (im->GetDimension() == 3))
117  {
118  // Use pixeltype&dimension specific read accessor
119 
120  int xlength = im->GetDimension(0);
121  int ylength = im->GetDimension(1);
122 
123  mitk::ImagePixelWriteAccessor<short, 2> writeAccessor(im, iDi);
124 
125  itk::Index<2> idx;
126  for (int i = 0; i < xlength; ++i)
127  {
128  for (int j = 0; j < ylength; ++j)
129  {
130  idx[0] = i;
131  idx[1] = j;
132  short newVal = rand() % 16000;
133  writeAccessor.SetPixelByIndexSafe(idx, newVal);
134  short val = writeAccessor.GetPixelByIndexSafe(idx);
135  if (val != newVal)
136  {
137  threadData->m_Successful = false;
138  }
139  }
140  }
141  }
142  else
143  {
144  // use general accessor
145  mitk::ImageWriteAccessor iB(im, iDi);
146  void *pointer = iB.GetData();
147  *((char *)pointer) = 0;
148  }
149  }
150  }
152  {
153  threadData->m_Successful = false;
154  e.Print(std::cout);
155  }
156  catch (mitk::Exception &e)
157  {
158  threadData->m_Successful = false;
159  e.Print(std::cout);
160  }
161 
162  // data processing end!
163  threadData->m_Barrier->Wait();
164  return ITK_THREAD_RETURN_VALUE;
165 }
166 
167 int mitkImageAccessorTest(int argc, char *argv[])
168 {
169  MITK_TEST_BEGIN("mitkImageAccessorTest");
170 
171  std::cout << "Loading file: ";
172  if (argc == 0)
173  {
174  std::cout << "no file specified [FAILED]" << std::endl;
175  return EXIT_FAILURE;
176  }
177  mitk::Image::Pointer image = NULL;
178  try
179  {
180  image = mitk::IOUtil::LoadImage(std::string(argv[1]));
181 
182  if (image.IsNull())
183  {
184  MITK_TEST_FAILED_MSG(<< "file could not be loaded [FAILED]")
185  }
186  }
187  catch (itk::ExceptionObject &ex)
188  {
189  MITK_TEST_FAILED_MSG(<< "Exception: " << ex << "[FAILED]")
190  }
191 
192  // CHECK INAPPROPRIATE AND SPECIAL USAGE
193 
194  // recursive mutex lock
195  MITK_TEST_OUTPUT(<< "Testing a recursive mutex lock attempt, should end in an exception ...");
196 
198  mitk::ImageWriteAccessor first(image);
199  mitk::ImageReadAccessor second(image);
201 
202  // ignore lock mechanism in read accessor
203  try
204  {
205  mitk::ImageWriteAccessor first(image);
207  MITK_TEST_CONDITION_REQUIRED(true, "Testing the option flag \"IgnoreLock\" in ReadAccessor");
208  }
209  catch (const mitk::Exception & /*e*/)
210  {
211  MITK_TEST_CONDITION_REQUIRED(false, "Ignoring the lock mechanism leads to exception.");
212  }
213 
214  // CREATE THREADS
215 
216  image->GetGeometry()->Initialize();
217 
219  unsigned int noOfThreads = 100;
220 
221  // initialize barrier
223  barrier->Initialize(noOfThreads + 1); // add one for we stop the base thread when the worker threads are processing
224 
225  ThreadData *threadData = new ThreadData;
226  threadData->m_Barrier = barrier;
227  threadData->m_NoOfThreads = noOfThreads;
228  threadData->data = image;
229  threadData->m_Successful = true;
230 
231  // spawn threads
232  for (unsigned int i = 0; i < noOfThreads; ++i)
233  {
234  threader->SpawnThread(ThreadMethod, threadData);
235  }
236  // stop the base thread during worker thread execution
237  barrier->Wait();
238 
239  // terminate threads
240  for (unsigned int j = 0; j < noOfThreads; ++j)
241  {
242  threader->TerminateThread(j);
243  }
244 
245  bool TestSuccessful = threadData->m_Successful;
246  delete threadData;
247 
248  MITK_TEST_CONDITION_REQUIRED(TestSuccessful, "Testing image access from multiple threads");
249 
250  MITK_TEST_END();
251 }
Gives locked and index-based write access for a particular image part. The class provides several set...
itk::SimpleFastMutexLock testMutex
itk::SmartPointer< Self > Pointer
const TPixel & GetPixelByIndexSafe(const itk::Index< VDimension > &idx) const
#define MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS)
Gives locked and index-based read access for a particular image part. The class provides several set-...
const TPixel & GetPixelByIndexSafe(const itk::Index< VDimension > &idx) const
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.
#define MITK_TEST_OUTPUT(x)
Output some text.
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
#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.
bool IsComplete() const
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.
static mitk::Image::Pointer LoadImage(const std::string &path)
LoadImage Convenience method to load an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:597
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.