1 /*****************************************************************************
4 ** Name: threadrecon.cpp
5 ** Purpose: Threaded reconstruction class
6 ** Programmer: Kevin Rosenberg
7 ** Date Started: February 2001
9 ** This is part of the CTSim program
10 ** Copyright (C) 1983-2009 Kevin Rosenberg
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License (version 2) as
14 ** published by the Free Software Foundation.
16 ** This program is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ** GNU General Public License for more details.
21 ** You should have received a copy of the GNU General Public License
22 ** along with this program; if not, write to the Free Software
23 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ******************************************************************************/
27 #include "wx/wxprec.h"
37 #include "threadrecon.h"
38 #include "backgroundmgr.h"
39 #include "backgroundsupr.h"
46 /////////////////////////////////////////////////////////////////////
48 // Class ReconstructorSupervisorThread -- Thread for Background Supervisor
50 /////////////////////////////////////////////////////////////////////
52 ReconstructorSupervisorThread::ReconstructorSupervisorThread (ProjectionFileView* pProjView, int iNX, int iNY,
53 const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
54 const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
55 const char* pszBackprojectName, wxChar const* pszLabel, ReconstructionROI* pROI, bool bRebinToParallel)
56 : SupervisorThread(), m_pProjView(pProjView), m_iNX(iNX), m_iNY(iNY), m_strFilterName(pszFilterName), m_dFilterParam(dFilterParam),
57 m_strFilterMethod(pszFilterMethod), m_iZeropad(iZeropad), m_strFilterGenerationName(pszFilterGenerationName),
58 m_strInterpName(pszInterpName), m_iInterpParam(iInterpParam), m_strBackprojectName(pszBackprojectName),
59 m_strLabel(pszLabel), m_reconROI(*pROI), m_bRebinToParallel(bRebinToParallel)
64 ReconstructorSupervisorThread::Entry()
66 Projections* pProj = &m_pProjView->GetDocument()->getProjections();
68 if (m_bRebinToParallel)
69 pProj = pProj->interpolateToParallel();
71 ReconstructorSupervisor reconSupervisor (this, pProj, m_pProjView, m_iNX, m_iNY,
72 m_strFilterName.c_str(), m_dFilterParam, m_strFilterMethod.c_str(), m_iZeropad, m_strFilterGenerationName.c_str(),
73 m_strInterpName.c_str(), m_iInterpParam, m_strBackprojectName.c_str(), m_strLabel, &m_reconROI);
75 reconSupervisor.start();
76 while (! reconSupervisor.workersDone() && ! reconSupervisor.fail() && ! reconSupervisor.cancelled()) {
79 if (reconSupervisor.fail())
81 wxString msg (_T("Error starting reconstructor supervisor: "));
82 msg += reconSupervisor.getFailMessage();
84 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
85 eventLog.SetString( msg );
86 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
88 if (! reconSupervisor.cancelled())
89 reconSupervisor.onDone();
90 reconSupervisor.deleteWorkers();
92 if (m_bRebinToParallel)
95 return static_cast<wxThread::ExitCode>(0);
99 ReconstructorSupervisorThread::OnExit()
104 /////////////////////////////////////////////////////////////////////
106 // Class ReconstructorSupervisor -- A Background Supervisor
108 /////////////////////////////////////////////////////////////////////
110 ReconstructorSupervisor::ReconstructorSupervisor (SupervisorThread* pThread, Projections* pProj,
111 ProjectionFileView* pProjView, int iImageNX, int iImageNY, const char* pszFilterName, double dFilterParam,
112 const char* pszFilterMethod, int iZeropad, const char* pszFilterGenerationName,
113 const char* pszInterpName, int iInterpParam, const char* pszBackprojectName, wxChar const* pszLabel,
114 ReconstructionROI* pROI)
115 : BackgroundSupervisor (pThread, pProjView->GetFrame(), pProjView->GetDocument(),
116 _T("Reconstructing"),
117 pProjView->GetDocument()->getProjections().nView()),
118 m_pProj(pProj), m_pProjView(pProjView), m_pProjDoc(pProjView->GetDocument()),
119 m_iImageNX(iImageNX), m_iImageNY(iImageNY),
120 m_pszFilterName(pszFilterName), m_dFilterParam(dFilterParam), m_pszFilterMethod(pszFilterMethod),
121 m_iZeropad(iZeropad), m_pszFilterGenerationName(pszFilterGenerationName), m_pszInterpName(pszInterpName),
122 m_iInterpParam(iInterpParam), m_pszBackprojectName(pszBackprojectName), m_strLabel(pszLabel),
125 m_vecpChildImageFile.reserve (getNumWorkers());
126 for (int iThread = 0; iThread < getNumWorkers(); iThread++) {
127 m_vecpChildImageFile[iThread] = new ImageFile (m_iImageNX, m_iImageNY);
132 ReconstructorSupervisor::~ReconstructorSupervisor()
134 for (int i = 0; i < getNumWorkers(); i++) {
135 delete m_vecpChildImageFile[i];
136 m_vecpChildImageFile[i] = NULL;
140 BackgroundWorkerThread*
141 ReconstructorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
143 ReconstructorWorker* pThread = new ReconstructorWorker (this, iThread, iStartUnit, iNumUnits);
144 pThread->SetParameters (m_pProj, m_pProjView, m_vecpChildImageFile[iThread], m_pszFilterName,
145 m_dFilterParam, m_pszFilterMethod, m_iZeropad, m_pszFilterGenerationName, m_pszInterpName,
146 m_iInterpParam, m_pszBackprojectName, m_pReconROI);
152 ReconstructorSupervisor::onDone()
154 wxCriticalSection doneSection;
155 wxCriticalSectionLocker critsect (doneSection);
157 ImageFile* pImageFile = getImageFile();
158 pImageFile->labelAdd (m_pProj->getLabel());
159 pImageFile->labelAdd (m_strLabel.mb_str(wxConvUTF8), getTimerEnd());
161 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
162 wxString msg (m_strLabel);
164 eventLog.SetString( msg );
165 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
167 wxCommandEvent newImageEvent (wxEVT_COMMAND_MENU_SELECTED, NEW_IMAGEFILE_EVENT);
168 newImageEvent.SetClientData (pImageFile);
169 wxPostEvent (theApp->getMainFrame(), newImageEvent);
176 ReconstructorSupervisor::getImageFile()
178 ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY);
179 pImageFile->arrayDataClear();
180 ImageFileArray pArray = pImageFile->getArray();
183 for (i = 0; i < getNumWorkers(); i++) {
184 ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray();
185 for (int ix = 0; ix < m_iImageNX; ix++)
186 for (int iy = 0; iy < m_iImageNY; iy++)
187 pArray[ix][iy] += pChildArray[ix][iy];
194 /////////////////////////////////////////////////////////////////////
196 // Class ReconstructorWorker -- A worker thread
198 /////////////////////////////////////////////////////////////////////
201 ReconstructorWorker::SetParameters (const Projections* pProj, ProjectionFileView* pProjView, ImageFile* pImageFile,
202 const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
203 const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
204 const char* pszBackprojectName, ReconstructionROI* pROI)
207 m_pProjView = pProjView;
208 m_pImageFile = pImageFile;
209 m_pszFilterName = pszFilterName;
210 m_dFilterParam = dFilterParam;
211 m_pszFilterMethod = pszFilterMethod;
212 m_iZeropad = iZeropad;
213 m_pszFilterGenerationName = pszFilterGenerationName;
214 m_pszInterpName = pszInterpName;
215 m_iInterpParam = iInterpParam;
216 m_pszBackprojectName = pszBackprojectName;
221 ReconstructorWorker::Entry ()
223 Reconstructor* pReconstructor = new Reconstructor (*m_pProj, *m_pImageFile, m_pszFilterName,
224 m_dFilterParam, m_pszFilterMethod, m_iZeropad, m_pszFilterGenerationName, m_pszInterpName,
225 m_iInterpParam, m_pszBackprojectName, Trace::TRACE_NONE, m_pReconROI, false);
227 bool bFail = pReconstructor->fail();
230 failMsg = _T("Unable to make reconstructor: ");
231 failMsg += wxConvUTF8.cMB2WX(pReconstructor->failMessage().c_str());
232 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
233 event.SetString( failMsg );
234 wxPostEvent( theApp->getMainFrame(), event );
238 wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
239 for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
242 if (theApp->getVerboseLogging()) {
244 msg.Printf(_T("Worker thread: Received destroy message at work unit #%d\n"), iUnit);
245 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
246 event.SetString( msg );
247 wxPostEvent( theApp->getMainFrame(), event );
252 pReconstructor->reconstructView (iUnit + m_iStartUnit, 1);
253 m_pSupervisor->onWorkerUnitTick();
255 pReconstructor->postProcessing();
257 delete pReconstructor;
260 m_pSupervisor->onWorkerFail (m_iThread, failMsg);
262 m_pSupervisor->onWorkerDone (m_iThread);
265 while (! TestDestroy())
268 return reinterpret_cast<wxThread::ExitCode>(0);
272 ReconstructorWorker::OnExit ()
276 #endif // HAVE_WXTHREADS