Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkThreadedToFRawDataReconstruction.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 // mitk includes
14 #include "mitkITKImageImport.h"
15 #include "mitkImageDataItem.h"
16 
17 // stl includes
18 #include <iostream>
19 #include <string>
20 #include <algorithm>
21 
22 // vtk includes
23 #include <vtkLookupTable.h>
24 #include <vtkFieldData.h>
25 #include <vtkSmartPointer.h>
26 
27 // itk includes
28 #include <itkMultiThreader.h>
29 #include <itksys/SystemTools.hxx>
30 
31 #ifdef WIN32
32 #include <winsock2.h>
33 #else
34 #include <arpa/inet.h>
35 #endif
36 #include <new>
37 
38 #define cAir 299704944;
39 #define fMod 20000000;
40 
41 namespace mitk
42 {
43 
45  m_CISDist(0), m_CISAmpl(0), m_CISInten(0),
46  m_ThreadedCISDist(0), m_ThreadedCISAmpl(0), m_ThreadedCISInten(0),
47  m_Init(0), m_Width(0), m_Height(0), m_SourceDataSize(0), m_ImageSize(0), m_SourceData(0)
48  {
51 
52  m_ThreadData->m_ImageDataMutex = itk::FastMutexLock::New();
53  m_ThreadData->m_ThreadDataMutex = itk::FastMutexLock::New();
54 
55  m_StackSize = 1;
56  }
57 
59  {
60  if(m_ThreadData != nullptr)
61  delete m_ThreadData;
62 
63  if(m_CISDist != nullptr)
64  delete[] m_CISDist;
65 
66  if(m_CISAmpl != nullptr)
67  delete[] m_CISAmpl;
68 
69  if(m_CISInten != nullptr)
70  delete[] m_CISInten;
71 
72  if(m_ThreadedCISInten != nullptr)
73  delete[] m_ThreadedCISInten;
74 
75  if(m_ThreadedCISAmpl != nullptr)
76  delete[] m_ThreadedCISAmpl;
77 
78  if(m_ThreadedCISDist != nullptr)
79  delete[] m_ThreadedCISDist;
80 
81  }
82 
83 void ThreadedToFRawDataReconstruction::Initialize(int width, int height, int modulationFrequency,
84  int sourceDataSize )
85 {
86  m_Width = width;
87  m_Height = height;
88  m_SourceDataSize = sourceDataSize;
89  m_ImageSize = width * height;
90  m_ThreadData->m_ModulationFrequency = modulationFrequency * 1e6;
91 
92  if(!m_Init)
93  {
94  m_SourceData = vtkShortArray::New();
95  m_SourceData->SetNumberOfComponents(m_SourceDataSize);
96  m_SourceData->SetNumberOfTuples(4);
97  m_SourceData->Allocate(1);
98 
99  m_CISDist = new float[m_ImageSize];
100  m_CISAmpl = new float[m_ImageSize];
101  m_CISInten = new float[m_ImageSize];
102  m_ThreadedCISDist = new float[m_ImageSize];
103  m_ThreadedCISAmpl = new float[m_ImageSize];
104  m_ThreadedCISInten = new float[m_ImageSize];
105 
109 
110  m_Init = true;
111  }
112 }
113 
115 {
116  m_SourceData->DeepCopy(sourceData);
117 }
118 
120 {
121  memcpy(dist, m_CISDist, m_ImageSize*sizeof(float) );
122 }
123 
125 {
126  memcpy(ampl, m_CISAmpl, m_ImageSize*sizeof(float));
127 }
128 
130 {
131  memcpy(inten, m_CISInten, m_ImageSize*sizeof(float));
132 }
133 
134 void ThreadedToFRawDataReconstruction::GetAllData(float* dist, float* ampl, float* inten)
135 {
136  memcpy(dist, m_CISDist, m_ImageSize*sizeof(float) );
137  memcpy(ampl, m_CISAmpl, m_ImageSize*sizeof(float));
138  memcpy(inten, m_CISInten, m_ImageSize*sizeof(float));
139 }
140 
142  {
143  if(m_Init)
144  {
146  }
147  }
148 
150  {
151  int sourceDataSize = m_SourceDataSize;
152  int lineWidth = m_Width;
153  int frameHeight = m_Height;
154  int channelSize = lineWidth*frameHeight << 1;
155  int quadChannelSize = channelSize * 0.25;
156 
157  std::vector<short> quad = std::vector<short>(quadChannelSize);
158 
159  // clean the thread data array
161 
162  int channelNo = 0;
163  while(channelNo < m_SourceData->GetNumberOfTuples())
164  {
165  short* sourceData = new short[channelSize];
166  m_SourceData->GetTupleValue(channelNo, sourceData);
167  quad.insert(quad.begin(), sourceData, sourceData+channelSize);
168  m_ThreadData->m_InputData.push_back(quad);
169  delete[]sourceData;
170  ++channelNo;
171  }
172 
173  if(m_Threader.IsNull())
174  {
175  m_Threader = this->GetMultiThreader();
176  }
177  int maxThreadNr = 0;
178 
179  if(m_Threader->GetGlobalDefaultNumberOfThreads()> 5)
180  {
181  maxThreadNr = 5;
182  }
183  else if(m_Threader->GetGlobalMaximumNumberOfThreads()>5)
184  {
185  maxThreadNr = 5;
186  }
187  else
188  {
189  maxThreadNr = m_Threader->GetGlobalMaximumNumberOfThreads();
190  }
191 
192  if ( m_ThreadData->m_Barrier.IsNull())
193  {
194  m_ThreadData->m_Barrier = itk::Barrier::New();
195  m_ThreadData->m_Barrier->Initialize(maxThreadNr);
196  }
197  m_ThreadData->m_DataSize = quadChannelSize;
198  m_ThreadData->m_LineWidth = lineWidth;
199  m_ThreadData->m_FrameHeight = frameHeight * 0.25;
200  std::vector<int> threadIDVector;
201  int threadcounter = 0;
202  while(threadcounter != maxThreadNr-1)
203  {
204  if (m_Threader->GetNumberOfThreads() < m_Threader->GetGlobalMaximumNumberOfThreads())
205  {
206  int threadID = m_Threader->SpawnThread(this->ThreadedGenerateDataCallbackFunction, m_ThreadData);
207  threadIDVector.push_back(threadID);
208  threadcounter++;
209  }
210  }
211  m_ThreadData->m_Barrier->Wait();
212 
213  int count = 0;
214  while(count != threadIDVector.size())
215  {
216  m_Threader->TerminateThread(threadIDVector.at(count));
217  count++;
218  }
220  memcpy(m_CISDist, m_ThreadData->m_OutputData.at(0), (channelSize * 0.5)*sizeof(float));
221  memcpy(m_CISAmpl, m_ThreadData->m_OutputData.at(1), (channelSize * 0.5)*sizeof(float));
222  memcpy(m_CISInten, m_ThreadData->m_OutputData.at(2), (channelSize * 0.5)*sizeof(float));
223  m_ThreadData->m_ImageDataMutex->Unlock();
224 
225  }
226 
228  {
229  /* extract this pointer from Thread Info structure */
230  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)data;
231  if (pInfo == nullptr)
232  {
233  return ITK_THREAD_RETURN_VALUE;
234  }
235  if (pInfo->UserData == nullptr)
236  {
237  return ITK_THREAD_RETURN_VALUE;
238  }
239  int quadrant = pInfo->ThreadID;
240  ThreadDataStruct* threadData = (ThreadDataStruct*) pInfo->UserData;
241 
242  // some needed variables
243  int x = 0;
244  double phi = 0;
245  double phi2 = 0;
246  double A1 = 0;
247  double A2 = 0;
248  double A3 = 0;
249  double A4 = 0;
250  double A5 = 0;
251  double A6 = 0;
252  double A7 = 0;
253  double A8 = 0;
254  double A3m1 = 0;
255  double A4m2 = 0;
256  double A7m5 = 0;
257  double A8m6 = 0;
258  double cair = cAir;
259  double twoPi = itk::Math::pi + itk::Math::pi;
260  long modFreq = fMod;
261 
262  threadData->m_ThreadDataMutex->Lock();
263  std::vector<short> quad1 = threadData->m_InputData.at(0);
264  std::vector<short> quad2 = threadData->m_InputData.at(1);
265  std::vector<short> quad3 = threadData->m_InputData.at(2);
266  std::vector<short> quad4 = threadData->m_InputData.at(3);
267  int index = quadrant << 1;
268  int index2 = 3-quadrant;
269  modFreq = threadData->m_ModulationFrequency;
270  int linewidth = threadData->m_LineWidth;
271  int frameheight = threadData->m_FrameHeight;
272  threadData->m_ThreadDataMutex->Unlock();
273 
274  double intermed1 = cair/(itk::Math::pi*(modFreq << 2));
275  double intermed2 = intermed1*500;
276  int doubleLwidth = linewidth << 1;
277  int datasize = doubleLwidth*frameheight << 2;
278 
279 
280  do
281  {
282  index += doubleLwidth;
283  x++;
284  do
285  {
286  index -= 8;
287  A1 = htons(quad1.at(index));
288  A2 = htons(quad2.at(index));
289  A3 = htons(quad3.at(index));
290  A4 = htons(quad4.at(index));
291  A5 = htons(quad1.at(index+1));
292  A6 = htons(quad2.at(index+1));
293  A7 = htons(quad3.at(index+1));
294  A8 = htons(quad4.at(index+1));
295 
296  phi = atan2((A3 - A1),(A2 - A4)) + itk::Math::pi;
297  phi2 = atan2((A7 - A5),(A6 - A8));
298  if(phi2<0) phi2 +=twoPi;
299 
300  A3m1 = A3*A3 - 2*A3*A1 + A1*A1;
301  A4m2 = A4*A4 - 2*A4*A2 + A2*A2;
302  A7m5 = A7*A7 - 2*A7*A5 + A5*A5;
303  A8m6 = A8*A8 - 2*A8*A6 + A6*A6;
304  threadData->m_ImageDataMutex->Lock();
305  threadData->m_OutputData.at(0)[index2] = (phi+phi2)*intermed2; //(((phi*intermed1) + (phi2*intermed1))/2)*1000;
306  threadData->m_OutputData.at(1)[index2] = (sqrt(A3m1 + A4m2)+sqrt(A7m5 + A8m6))*0.5; //(sqrt(A3m1 + A4m2)/2) + (sqrt(A7m5 + A8m6)/2);
307  threadData->m_OutputData.at(2)[index2] = (A1+A2+A3+A4+A5+A6+A7+A8)*0.125;
308  threadData->m_ImageDataMutex->Unlock();
309 
310  index2 += 4;
311  }while(index2 <= (x*linewidth) - (1+quadrant));
312 
313  index += doubleLwidth;
314 
315  }while(index < datasize);
316 
317  threadData->m_Barrier->Wait();
318 
319  return ITK_THREAD_RETURN_VALUE;
320  }
321 
323  {
324  this->GenerateData();
325  }
326 
327 } // end mitk namespace
void Initialize(int width, int height, int modulationFrequency, int sourceDataSize)
itk::FastMutexLock::Pointer m_ImageDataMutex
mutex for coordinated access to image data
virtual void GenerateData()
method generating the outputs of this filter. Called in the updated process of the pipeline...
float * m_CISDist
holds the distance information from for one distance image slice
DataCollection - Class to facilitate loading/accessing structured data.
float * m_CISAmpl
holds the amplitude information from for one amplitude image slice
itk::Barrier::Pointer m_Barrier
barrier to synchronize ends of threads
std::vector< std::vector< short > > m_InputData
static ITK_THREAD_RETURN_TYPE ThreadedGenerateDataCallbackFunction(void *data)
threader callback function for multi threaded data generation
float * m_CISInten
holds the intensity information from for one intensity image slice
virtual void BeforeThreadedGenerateData()
method configures the camera output and prepares the thread data struct for threaded data generation ...
itk::FastMutexLock::Pointer m_ThreadDataMutex
mutex to control access to images
void GetAllData(float *dist, float *ampl, float *inten)