Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.