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-2001 Kevin Rosenberg
12 ** $Id: threadrecon.cpp,v 1.14 2001/02/27 03:59:30 kevin Exp $
14 ** This program is free software; you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License (version 2) as
16 ** published by the Free Software Foundation.
18 ** This program is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ** GNU General Public License for more details.
23 ** You should have received a copy of the GNU General Public License
24 ** along with this program; if not, write to the Free Software
25 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ******************************************************************************/
28 #include "wx/wxprec.h"
38 #include "threadrecon.h"
39 #include "backgroundmgr.h"
40 #include "backgroundsupr.h"
42 #if defined(HAVE_CONFIG_H)
48 /////////////////////////////////////////////////////////////////////
50 // Class ReconstructorSupervisorThread -- Thread for Background Supervisor
52 /////////////////////////////////////////////////////////////////////
54 ReconstructorSupervisorThread::ReconstructorSupervisorThread (ProjectionFileView* pProjView, int iNX, int iNY,
55 const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
56 const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
57 const char* pszBackprojectName, const char* const pszLabel)
58 : m_pProjView(pProjView), m_iNX(iNX), m_iNY(iNY), m_strFilterName(pszFilterName), m_dFilterParam(dFilterParam),
59 m_strFilterMethod(pszFilterMethod), m_iZeropad(iZeropad), m_strFilterGenerationName(pszFilterGenerationName),
60 m_strInterpName(pszInterpName), m_iInterpParam(iInterpParam), m_strBackprojectName(pszBackprojectName), m_strLabel(pszLabel),
66 ReconstructorSupervisorThread::Entry()
68 ReconstructorSupervisor reconSupervisor (this, m_pProjView, m_iNX, m_iNY,
69 m_strFilterName.c_str(), m_dFilterParam, m_strFilterMethod.c_str(), m_iZeropad, m_strFilterGenerationName.c_str(),
70 m_strInterpName.c_str(), m_iInterpParam, m_strBackprojectName.c_str(), m_strLabel.c_str());
72 reconSupervisor.start();
73 while (! reconSupervisor.isDone() && ! reconSupervisor.fail()) {
77 if (reconSupervisor.fail())
79 wxString msg ("Error starting reconstructor supervisor: ");
80 msg += reconSupervisor.getFailMessage().c_str();
82 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
83 eventLog.SetString( msg );
84 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
87 while (! reconSupervisor.workersDeleted()) {
89 reconSupervisor.ProcessPendingEvents();
92 return reinterpret_cast<wxThread::ExitCode>(0);
96 ReconstructorSupervisorThread::OnExit()
101 /////////////////////////////////////////////////////////////////////
103 // Class ReconstructorSupervisor -- A Background Supervisor
105 /////////////////////////////////////////////////////////////////////
107 ReconstructorSupervisor::ReconstructorSupervisor (SupervisorThread* pThread, ProjectionFileView* pProjView,
108 int iImageNX, int iImageNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod,
109 int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
110 const char* pszBackprojectName, const char* const pszLabel)
111 : m_pProjView(pProjView), m_pProjDoc(pProjView->GetDocument()),
112 m_iImageNX(iImageNX), m_iImageNY(iImageNY),
113 m_pszFilterName(pszFilterName), m_dFilterParam(dFilterParam), m_pszFilterMethod(pszFilterMethod),
114 m_iZeropad(iZeropad), m_pszFilterGenerationName(pszFilterGenerationName), m_pszInterpName(pszInterpName),
115 m_iInterpParam(iInterpParam), m_pszBackprojectName(pszBackprojectName), m_pszLabel(pszLabel),
116 BackgroundSupervisor (pThread, pProjView->GetFrame(), pProjView->GetDocument(), "Reconstructing", pProjView->GetDocument()->getProjections().nView())
118 m_vecpChildImageFile.reserve (getNumWorkers());
119 for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
120 m_vecpChildImageFile[iThread] = new ImageFile (m_iImageNX, m_iImageNY);
125 ReconstructorSupervisor::~ReconstructorSupervisor()
127 for (int i = 0; i < getNumWorkers(); i++) {
128 delete m_vecpChildImageFile[i];
129 m_vecpChildImageFile[i] = NULL;
133 BackgroundWorkerThread*
134 ReconstructorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
136 ReconstructorWorker* pThread = new ReconstructorWorker (this, iThread, iStartUnit, iNumUnits);
137 pThread->SetParameters (m_pProjView, m_vecpChildImageFile[iThread], m_pszFilterName, m_dFilterParam,
138 m_pszFilterMethod, m_iZeropad, m_pszFilterGenerationName, m_pszInterpName,
139 m_iInterpParam, m_pszBackprojectName);
145 ReconstructorSupervisor::onDone()
147 wxCriticalSection doneSection;
148 wxCriticalSectionLocker critsect (doneSection);
150 ImageFileDocument* pReconDoc = theApp->newImageDoc();
152 sys_error (ERR_SEVERE, "Unable to create image file");
156 ImageFile* pImageFile = getImageFile();
157 pReconDoc->setImageFile (pImageFile);
158 if (theApp->getAskDeleteNewDocs())
159 pReconDoc->Modify (true);
160 pReconDoc->UpdateAllViews (m_pProjView);
161 if (ImageFileView* rasterView = pReconDoc->getView()) {
162 rasterView->OnUpdate (rasterView, NULL);
163 rasterView->getFrame()->SetFocus();
164 rasterView->getFrame()->Show(true);
166 *theApp->getLog() << m_pszLabel << "\n";
167 pImageFile->labelAdd (m_pProjView->GetDocument()->getProjections().getLabel());
168 pImageFile->labelAdd (m_pszLabel, getTimerEnd());
175 ReconstructorSupervisor::getImageFile()
177 ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY);
178 pImageFile->arrayDataClear();
179 ImageFileArray pArray = pImageFile->getArray();
182 for (i = 0; i < getNumWorkers(); i++) {
183 ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray();
184 for (int ix = 0; ix < m_iImageNX; ix++)
185 for (int iy = 0; iy < m_iImageNY; iy++)
186 pArray[ix][iy] += pChildArray[ix][iy];
193 /////////////////////////////////////////////////////////////////////
195 // Class ReconstructorWorker -- A worker thread
197 /////////////////////////////////////////////////////////////////////
200 ReconstructorWorker::SetParameters (ProjectionFileView* pProjView, ImageFile* pImageFile,
201 const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
202 const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
203 const char* pszBackprojectName)
205 m_pProjView = pProjView;
206 m_pImageFile = pImageFile;
207 m_pszFilterName = pszFilterName;
208 m_dFilterParam = dFilterParam;
209 m_pszFilterMethod = pszFilterMethod;
210 m_iZeropad = iZeropad;
211 m_pszFilterGenerationName = pszFilterGenerationName;
212 m_pszInterpName = pszInterpName;
213 m_iInterpParam = iInterpParam;
214 m_pszBackprojectName = pszBackprojectName;
218 ReconstructorWorker::Entry ()
220 Reconstructor* pReconstructor = new Reconstructor (m_pProjView->GetDocument()->getProjections(),
221 *m_pImageFile, m_pszFilterName, m_dFilterParam, m_pszFilterMethod, m_iZeropad,
222 m_pszFilterGenerationName, m_pszInterpName, m_iInterpParam, m_pszBackprojectName, Trace::TRACE_NONE);
224 bool bFail = pReconstructor->fail();
227 failMsg = "Unable to make reconstructor: ";
228 failMsg += pReconstructor->failMessage().c_str();
229 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
230 event.SetString( failMsg );
231 wxPostEvent( theApp->getMainFrame(), event );
235 wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
236 for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
239 if (theApp->getVerboseLogging()) {
241 msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);
242 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
243 event.SetString( msg );
244 wxPostEvent( theApp->getMainFrame(), event );
249 pReconstructor->reconstructView (iUnit + m_iStartUnit, 1);
250 m_pSupervisor->AddPendingEvent (eventProgress);
252 pReconstructor->postProcessing();
254 delete pReconstructor;
257 wxCommandEvent eventFail (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_FAIL);
258 eventFail.SetInt (m_iThread); // Send back thread# that has finished
259 eventFail.SetString (failMsg);
260 wxPostEvent (m_pSupervisor, eventFail);
262 wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
263 eventDone.SetInt (m_iThread); // Send back thread# that has finished
264 wxPostEvent (m_pSupervisor, eventDone);
267 while (! TestDestroy())
270 return reinterpret_cast<wxThread::ExitCode>(0);
274 ReconstructorWorker::OnExit ()