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.1 2001/02/25 10:52:55 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 "threadproj.h"
39 #include "backgroundmgr.h"
40 #include "backgroundsupr.h"
42 #if defined(HAVE_CONFIG_H)
48 /////////////////////////////////////////////////////////////////////
50 // Class ProjectorSupervisorThread -- Thread for Background Supervisor
52 /////////////////////////////////////////////////////////////////////
54 ProjectorSupervisorThread::ProjectorSupervisorThread (PhantomFileView* pProjView, int iNDet, int iNView,
55 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dViewRatio,
56 double dScanRatio, const char* const pszLabel)
57 : m_pPhantomView(pProjView), m_iNDet(iNDet), m_iNView(iNView), m_strGeometry(pszGeometry),
58 m_iNSample(iNSample), m_dRotation(dRotation), m_dFocalLength(dFocalLength), m_dViewRatio(dViewRatio),
59 m_dScanRatio(dScanRatio), m_strLabel(pszLabel),
65 ProjectorSupervisorThread::Entry()
67 ProjectorSupervisor projSupervisor (m_pPhantomView, m_iNDet, m_iNView,
68 m_strGeometry.c_str(), m_iNSample, m_dRotation, m_dFocalLength, m_dViewRatio, m_dScanRatio, m_strLabel.c_str());
70 projSupervisor.start();
71 while (! projSupervisor.isDone() && ! projSupervisor.fail()) {
75 if (projSupervisor.fail())
77 wxString msg ("Error starting Projector supervisor: ");
78 msg += projSupervisor.getFailMessage().c_str();
80 wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
81 eventLog.SetString( msg );
82 wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
85 while (! projSupervisor.workersDeleted()) {
87 projSupervisor.ProcessPendingEvents();
90 return reinterpret_cast<wxThread::ExitCode>(0);
94 ProjectorSupervisorThread::OnExit()
99 /////////////////////////////////////////////////////////////////////
101 // Class ProjectorSupervisor -- A Background Supervisor
103 /////////////////////////////////////////////////////////////////////
105 ProjectorSupervisor::ProjectorSupervisor (PhantomFileView* pPhantomView, int iNDet, int iNView,
106 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dViewRatio,
107 double dScanRatio, const char* const pszLabel)
108 : m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()),
109 m_iNDet(iNDet), m_iNView(iNView),
110 m_pszGeometry(pszGeometry), m_iNSample(iNSample), m_dRotation(dRotation), m_dFocalLength(dFocalLength),
111 m_dViewRatio(dViewRatio), m_dScanRatio(dScanRatio), m_pszLabel(pszLabel),
112 BackgroundSupervisor (pPhantomView->GetFrame(), pPhantomView->GetDocument(), "Projecting", iNView)
114 m_vecpChildProjections.reserve (getNumWorkers());
115 for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
116 m_vecpChildProjections[iThread] = new Projections (m_iNDet, m_iNView);
121 ProjectorSupervisor::~ProjectorSupervisor()
123 for (int i = 0; i < getNumWorkers(); i++) {
124 delete m_vecpChildProjections[i];
125 m_vecpChildProjections[i] = NULL;
129 BackgroundWorkerThread*
130 ProjectorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
132 ProjectorWorker* pThread = new ProjectorWorker (this, iThread, iStartUnit, iNumUnits);
133 pThread->SetParameters (m_pPhantomView, m_vecpChildProjections[iThread], m_iNDet, m_iNView,
134 m_pszGeometry, m_iNSample, m_dRotation, m_dFocalLength, m_dViewRatio, m_dScanRatio);
140 ProjectorSupervisor::onDone()
142 wxCriticalSection doneSection;
143 wxCriticalSectionLocker critsect (doneSection);
145 ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
147 sys_error (ERR_SEVERE, "Unable to create projection file");
151 Projections* pProjections = getProjections();
152 pProjDoc->setProjections (pProjections);
153 if (theApp->getAskDeleteNewDocs())
154 pProjDoc->Modify (true);
155 pProjDoc->UpdateAllViews (NULL);
156 if (ProjectionFileView* projView = pProjDoc->getView()) {
157 projView->OnUpdate (projView, NULL);
158 projView->getFrame()->SetFocus();
159 projView->getFrame()->Show(true);
161 *theApp->getLog() << m_pszLabel << "\n";
162 pProjections->setRemark (m_pszLabel);
163 pProjections->setCalcTime (getTimerEnd());
170 ProjectorSupervisor::getProjections()
172 Projections* pProjections = new Projections (m_iNDet, m_iNView);
174 ImageFileArray pArray = pImageFile->getArray();
177 for (i = 0; i < getNumWorkers(); i++) {
178 ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray();
179 for (int ix = 0; ix < m_iImageNX; ix++)
180 for (int iy = 0; iy < m_iImageNY; iy++)
181 pArray[ix][iy] += pChildArray[ix][iy];
184 return (pProjections);
188 /////////////////////////////////////////////////////////////////////
190 // Class ProjectorWorker -- A worker thread
192 /////////////////////////////////////////////////////////////////////
195 ProjectorWorker::SetParameters (PhantomFileView* pPhantomView, Projections* pProjections, int iNDet, int iView,
196 const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dViewRatio,
199 m_pPhantomView = pPhantomView;
200 m_pProjections = pProjections;
201 m_pszGeometry = pszGeometry;
202 m_iNSample = iNSample;
203 m_dFocalLength = dFocalLength;
204 m_dViewRatio = dViewRatio;
205 m_dScanRatio = dScanRatio;
209 ProjectorWorker::Entry ()
211 const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
212 Scanner* pScanner = new Scanner (rPhantom, m_pszGeometry, m_iNDet,
213 m_iNView, m_iNSample, m_dRotation, m_dFocalLength, m_dViewRatio, m_dScanRatio);
215 bool bFail = pScanner->fail();
218 failMsg = "Unable to make Projector: ";
219 failMsg += pScanner->failMessage().c_str();
220 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
221 event.SetString( failMsg );
222 wxPostEvent( theApp->getMainFrame(), event );
226 wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
227 for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
230 if (theApp->getVerboseLogging()) {
232 msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);
233 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
234 event.SetString( msg );
235 wxPostEvent( theApp->getMainFrame(), event );
240 pScanner->collectProjections (*m_pProjections, rPhantom, iUnit + m_iStartUnit, 1, true, Trace::TRACE_NONE);
241 wxPostEvent (m_pSupervisor, eventProgress);
247 wxCommandEvent eventFail (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_FAIL);
248 eventFail.SetInt (m_iThread); // Send back thread# that has finished
249 eventFail.SetString (failMsg);
250 wxPostEvent (m_pSupervisor, eventFail);
252 wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
253 eventDone.SetInt (m_iThread); // Send back thread# that has finished
254 wxPostEvent (m_pSupervisor, eventDone);
257 while (! TestDestroy())
260 return reinterpret_cast<wxThread::ExitCode>(0);
264 ProjectorWorker::OnExit ()