1 /*****************************************************************************
4 ** Name: threadproj.cpp
5 ** Purpose: Threaded projection 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: threadproj.cpp,v 1.7 2001/03/02 21:11:50 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"
34 #if defined(HAVE_CONFIG_H)
42 #include "threadproj.h"
43 #include "backgroundmgr.h"
44 #include "backgroundsupr.h"
51 /////////////////////////////////////////////////////////////////////
53 // Class ProjectorSupervisorThread -- Thread for Background Supervisor
55 /////////////////////////////////////////////////////////////////////
57 ProjectorSupervisorThread::ProjectorSupervisorThread (PhantomFileView* pProjView, int iNDet, int iNView,
58 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
59 double dViewRatio, double dScanRatio, const char* const pszLabel)
60 : m_pPhantomView(pProjView), m_iNDet(iNDet), m_iNView(iNView), m_strGeometry(pszGeometry),
61 m_iNSample(iNSample), m_dRotation(dRotation), m_dFocalLength(dFocalLength), m_dCenterDetectorLength(dCenterDetectorLength),
62 m_dViewRatio(dViewRatio), m_dScanRatio(dScanRatio), m_strLabel(pszLabel),
68 ProjectorSupervisorThread::Entry()
70 ProjectorSupervisor projSupervisor (this, m_pPhantomView, m_iNDet, m_iNView,
71 m_strGeometry.c_str(), m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio, m_strLabel.c_str());
73 projSupervisor.start();
74 while (! projSupervisor.isDone() && ! projSupervisor.fail()) {
78 if (projSupervisor.fail())
80 wxString msg ("Error starting Projector supervisor: ");
81 msg += projSupervisor.getFailMessage().c_str();
83 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
84 eventLog.SetString( msg );
85 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
88 while (! projSupervisor.workersDeleted()) {
90 projSupervisor.ProcessPendingEvents();
93 return reinterpret_cast<wxThread::ExitCode>(0);
97 ProjectorSupervisorThread::OnExit()
102 /////////////////////////////////////////////////////////////////////
104 // Class ProjectorSupervisor -- A Background Supervisor
106 /////////////////////////////////////////////////////////////////////
108 ProjectorSupervisor::ProjectorSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNDet, int iNView,
109 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
110 double dViewRatio, double dScanRatio, const char* const pszLabel)
111 : m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()),
112 m_iNDet(iNDet), m_iNView(iNView),
113 m_pszGeometry(pszGeometry), m_iNSample(iNSample), m_dRotation(dRotation), m_dFocalLength(dFocalLength),
114 m_dCenterDetectorLength(dCenterDetectorLength), m_dViewRatio(dViewRatio), m_dScanRatio(dScanRatio), m_pszLabel(pszLabel),
115 BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), "Projecting", iNView)
117 m_pScanner = new Scanner (m_pPhantomDoc->getPhantom(), m_pszGeometry, m_iNDet,
118 m_iNView, m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio);
120 m_vecpChildProjections.reserve (getNumWorkers());
121 for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
122 m_vecpChildProjections[iThread] = new Projections (*m_pScanner);
129 ProjectorSupervisor::~ProjectorSupervisor()
131 for (int i = 0; i < getNumWorkers(); i++) {
132 delete m_vecpChildProjections[i];
133 m_vecpChildProjections[i] = NULL;
139 BackgroundWorkerThread*
140 ProjectorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
142 ProjectorWorker* pThread = new ProjectorWorker (this, iThread, iStartUnit, iNumUnits);
143 m_vecpChildProjections[iThread]->setNView (iNumUnits);
144 pThread->SetParameters (m_pPhantomView, m_vecpChildProjections[iThread], m_pScanner, m_iNDet, m_iNView,
145 m_pszGeometry, m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio);
151 ProjectorSupervisor::onDone()
153 wxCriticalSection doneSection;
154 wxCriticalSectionLocker critsect (doneSection);
156 Projections* pProjections = getProjections();
159 ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
161 sys_error (ERR_SEVERE, "Unable to create projection file");
164 pProjDoc->setProjections (pProjections);
165 pProjDoc->UpdateAllViews (NULL);
166 if (ProjectionFileView* projView = pProjDoc->getView()) {
167 projView->OnUpdate (projView, NULL);
168 projView->getFrame()->SetFocus();
169 projView->getFrame()->Show(true);
171 *theApp->getLog() << m_pszLabel << "\n";
174 if (theApp->getAskDeleteNewDocs())
175 pProjDoc->Modify (true);
176 pProjections->setRemark (m_pszLabel);
177 pProjections->setCalcTime (getTimerEnd());
184 ProjectorSupervisor::getProjections()
186 Projections* pProjections = new Projections (*m_pScanner);
189 size_t detArraySize = pProjections->nDet() * sizeof (DetectorValue);
190 for (int iw = 0; iw < getNumWorkers(); iw++) {
191 for (int iView = 0; iView < m_vecpChildProjections[iw]->nView(); iView++) {
192 DetectorArray& childDetArray = m_vecpChildProjections[iw]->getDetectorArray(iView);
193 DetectorArray& globalDetArray = pProjections->getDetectorArray(iGlobalView++);
194 globalDetArray.setViewAngle (childDetArray.viewAngle());
195 DetectorValue* childDetval = childDetArray.detValues();
196 DetectorValue* globalDetval = globalDetArray.detValues();
197 memcpy (globalDetval, childDetval, detArraySize);
201 return (pProjections);
205 /////////////////////////////////////////////////////////////////////
207 // Class ProjectorWorker -- A worker thread
209 /////////////////////////////////////////////////////////////////////
212 ProjectorWorker::SetParameters (PhantomFileView* pPhantomView, Projections* pProjections, Scanner* pScanner,
213 int iNDet, int iView,
214 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
215 double dViewRatio, double dScanRatio)
217 m_pScanner = pScanner;
218 m_pPhantomView = pPhantomView;
219 m_pProjections = pProjections;
220 m_pszGeometry = pszGeometry;
221 m_iNSample = iNSample;
222 m_dFocalLength = dFocalLength;
223 m_dCenterDetectorLength = dCenterDetectorLength;
224 m_dViewRatio = dViewRatio;
225 m_dScanRatio = dScanRatio;
229 ProjectorWorker::Entry ()
231 const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
232 bool bFail = m_pScanner->fail();
235 failMsg = "Unable to make Projector: ";
236 failMsg += m_pScanner->failMessage().c_str();
237 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
238 event.SetString( failMsg );
239 wxPostEvent( theApp->getMainFrame(), event );
243 wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
244 for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
247 if (theApp->getVerboseLogging()) {
249 msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);
250 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
251 event.SetString( msg );
252 wxPostEvent( theApp->getMainFrame(), event );
257 m_pScanner->collectProjections (*m_pProjections, rPhantom, iUnit + m_iStartUnit, 1, iUnit, Trace::TRACE_NONE);
258 wxPostEvent (m_pSupervisor, eventProgress);
263 wxCommandEvent eventFail (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_FAIL);
264 eventFail.SetInt (m_iThread); // Send back thread# that has finished
265 eventFail.SetString (failMsg);
266 wxPostEvent (m_pSupervisor, eventFail);
268 wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
269 eventDone.SetInt (m_iThread); // Send back thread# that has finished
270 wxPostEvent (m_pSupervisor, eventDone);
273 while (! TestDestroy())
276 return reinterpret_cast<wxThread::ExitCode>(0);
280 ProjectorWorker::OnExit ()
284 #endif // HAVE_WXTHREADS