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-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 ******************************************************************************/
26 #include "wx/wxprec.h"
32 #if defined(HAVE_CONFIG_H)
40 #include "threadproj.h"
41 #include "backgroundmgr.h"
42 #include "backgroundsupr.h"
49 /////////////////////////////////////////////////////////////////////
51 // Class ProjectorSupervisorThread -- Thread for Background Supervisor
53 /////////////////////////////////////////////////////////////////////
55 ProjectorSupervisorThread::ProjectorSupervisorThread (PhantomFileView* pProjView, int iNDet, int iNView, int iOffsetView,
56 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
57 double dViewRatio, double dScanRatio, wxChar const* pszLabel)
58 : SupervisorThread(), m_pPhantomView(pProjView), m_iNDet(iNDet), m_iNView(iNView), m_iOffsetView(iOffsetView), m_strGeometry(pszGeometry),
59 m_iNSample(iNSample), m_dRotation(dRotation), m_dFocalLength(dFocalLength), m_dCenterDetectorLength(dCenterDetectorLength),
60 m_dViewRatio(dViewRatio), m_dScanRatio(dScanRatio), m_strLabel(pszLabel)
65 ProjectorSupervisorThread::Entry()
67 ProjectorSupervisor projSupervisor (this, m_pPhantomView, m_iNDet, m_iNView, m_iOffsetView,
68 m_strGeometry.c_str(), m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio, m_strLabel);
70 projSupervisor.start();
71 while (! projSupervisor.workersDone() && ! projSupervisor.fail() && ! projSupervisor.cancelled()) {
74 if (projSupervisor.fail())
76 wxString msg (_T("Error starting Projector supervisor: "));
77 msg += projSupervisor.getFailMessage();
79 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
80 eventLog.SetString( msg );
81 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
84 if (! projSupervisor.cancelled())
85 projSupervisor.onDone();
86 projSupervisor.deleteWorkers();
88 return static_cast<wxThread::ExitCode>(0);
92 ProjectorSupervisorThread::OnExit()
97 /////////////////////////////////////////////////////////////////////
99 // Class ProjectorSupervisor -- A Background Supervisor
101 /////////////////////////////////////////////////////////////////////
103 ProjectorSupervisor::ProjectorSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNDet, int iNView, int iOffsetView,
104 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
105 double dViewRatio, double dScanRatio, wxChar const* pszLabel)
106 : BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), _T("Projecting"), iNView),
107 m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()),
108 m_iNDet(iNDet), m_iNView(iNView), m_iOffsetView(iOffsetView), m_pszGeometry(pszGeometry), m_iNSample(iNSample),
109 m_dRotation(dRotation), m_dFocalLength(dFocalLength), m_dCenterDetectorLength(dCenterDetectorLength),
110 m_dViewRatio(dViewRatio), m_dScanRatio(dScanRatio), m_strLabel(pszLabel)
112 m_pScanner = new Scanner (m_pPhantomDoc->getPhantom(), m_pszGeometry, m_iNDet,
113 m_iNView, m_iOffsetView, m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio);
115 m_vecpChildProjections.reserve (getNumWorkers());
116 for (int iThread = 0; iThread < getNumWorkers(); iThread++) {
117 m_vecpChildProjections[iThread] = new Projections (*m_pScanner);
124 ProjectorSupervisor::~ProjectorSupervisor()
126 for (int i = 0; i < getNumWorkers(); i++) {
127 delete m_vecpChildProjections[i];
128 m_vecpChildProjections[i] = NULL;
134 BackgroundWorkerThread*
135 ProjectorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
137 ProjectorWorker* pThread = new ProjectorWorker (this, iThread, iStartUnit, iNumUnits);
138 m_vecpChildProjections[iThread]->setNView (iNumUnits);
139 pThread->SetParameters (m_pPhantomView, m_vecpChildProjections[iThread], m_pScanner, m_iNDet, m_iNView, m_iOffsetView,
140 m_pszGeometry, m_iNSample, m_dRotation, m_dFocalLength, m_dCenterDetectorLength, m_dViewRatio, m_dScanRatio);
146 ProjectorSupervisor::onDone()
148 wxCriticalSection doneSection;
149 wxCriticalSectionLocker critsect (doneSection);
151 Projections* pProjections = getProjections();
152 pProjections->setRemark (m_strLabel.mb_str(wxConvUTF8));
153 pProjections->setCalcTime (getTimerEnd());
155 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
156 wxString msg (m_strLabel);
158 eventLog.SetString( msg );
159 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
161 wxCommandEvent newProjEvent (wxEVT_COMMAND_MENU_SELECTED, NEW_PROJECTIONFILE_EVENT);
162 newProjEvent.SetClientData (pProjections);
163 wxPostEvent (theApp->getMainFrame(), newProjEvent);
170 ProjectorSupervisor::getProjections()
172 Projections* pProjections = new Projections (*m_pScanner);
175 size_t detArraySize = pProjections->nDet() * sizeof (DetectorValue);
176 for (int iw = 0; iw < getNumWorkers(); iw++) {
177 for (int iView = 0; iView < m_vecpChildProjections[iw]->nView(); iView++) {
178 DetectorArray& childDetArray = m_vecpChildProjections[iw]->getDetectorArray(iView);
179 DetectorArray& globalDetArray = pProjections->getDetectorArray(iGlobalView++);
180 globalDetArray.setViewAngle (childDetArray.viewAngle());
181 DetectorValue* childDetval = childDetArray.detValues();
182 DetectorValue* globalDetval = globalDetArray.detValues();
183 memcpy (globalDetval, childDetval, detArraySize);
187 return (pProjections);
191 /////////////////////////////////////////////////////////////////////
193 // Class ProjectorWorker -- A worker thread
195 /////////////////////////////////////////////////////////////////////
198 ProjectorWorker::SetParameters (PhantomFileView* pPhantomView, Projections* pProjections, Scanner* pScanner,
199 int iNDet, int iView, int iOffsetView,
200 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dCenterDetectorLength,
201 double dViewRatio, double dScanRatio)
203 m_pScanner = pScanner;
204 m_pPhantomView = pPhantomView;
205 m_pProjections = pProjections;
206 m_pszGeometry = pszGeometry;
207 m_iNSample = iNSample;
208 m_dFocalLength = dFocalLength;
209 m_dCenterDetectorLength = dCenterDetectorLength;
210 m_dViewRatio = dViewRatio;
211 m_dScanRatio = dScanRatio;
215 ProjectorWorker::Entry ()
217 const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
218 bool bFail = m_pScanner->fail();
221 failMsg = _T("Unable to make Projector: ");
222 failMsg += wxConvUTF8.cMB2WX(m_pScanner->failMessage().c_str());
223 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
224 event.SetString( failMsg );
225 wxPostEvent( theApp->getMainFrame(), event );
229 wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
230 for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
233 if (theApp->getVerboseLogging()) {
235 msg.Printf(_T("Worker thread: Received destroy message at work unit #%d\n"), iUnit);
236 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
237 event.SetString( msg );
238 wxPostEvent( theApp->getMainFrame(), event );
243 m_pScanner->collectProjections (*m_pProjections, rPhantom, iUnit + m_iStartUnit, 1,
244 m_iOffsetView, iUnit, Trace::TRACE_NONE);
245 m_pSupervisor->onWorkerUnitTick();
250 m_pSupervisor->onWorkerFail (m_iThread, failMsg);
252 m_pSupervisor->onWorkerDone (m_iThread);
255 while (! TestDestroy())
258 return reinterpret_cast<wxThread::ExitCode>(0);
262 ProjectorWorker::OnExit ()
266 #endif // HAVE_WXTHREADS