Revert "Update package dependency from libwxgtk3.0-dev to libwxgtk3.0-gtk3-dev for...
[ctsim.git] / src / threadproj.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          threadproj.cpp
5 **   Purpose:       Threaded projection class
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  February 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2009 Kevin Rosenberg
11 **
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.
15 **
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.
20 **
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 ******************************************************************************/
25
26 #include "wx/wxprec.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/wx.h"
30 #endif
31
32 #if defined(HAVE_CONFIG_H)
33 #include "config.h"
34 #endif
35
36 #include "ct.h"
37 #include "ctsim.h"
38 #include "docs.h"
39 #include "views.h"
40 #include "threadproj.h"
41 #include "backgroundmgr.h"
42 #include "backgroundsupr.h"
43
44 #ifdef HAVE_WXTHREADS
45
46
47
48
49 /////////////////////////////////////////////////////////////////////
50 //
51 // Class ProjectorSupervisorThread -- Thread for Background Supervisor
52 //
53 /////////////////////////////////////////////////////////////////////
54
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)
61 {
62 }
63
64 wxThread::ExitCode
65 ProjectorSupervisorThread::Entry()
66 {
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);
69
70   projSupervisor.start();
71   while (! projSupervisor.workersDone() && ! projSupervisor.fail() && ! projSupervisor.cancelled()) {
72     Sleep(100);
73   }
74   if (projSupervisor.fail())
75   {
76     wxString msg (_T("Error starting Projector supervisor: "));
77     msg += projSupervisor.getFailMessage();
78     msg += _T("\n");
79     wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
80     eventLog.SetString( msg );
81     wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
82   }
83
84   if (! projSupervisor.cancelled())
85           projSupervisor.onDone();
86   projSupervisor.deleteWorkers();
87
88   return static_cast<wxThread::ExitCode>(0);
89 }
90
91 void
92 ProjectorSupervisorThread::OnExit()
93 {
94 }
95
96
97 /////////////////////////////////////////////////////////////////////
98 //
99 // Class ProjectorSupervisor -- A Background Supervisor
100 //
101 /////////////////////////////////////////////////////////////////////
102
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)
111 {
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);
114
115   m_vecpChildProjections.reserve (getNumWorkers());
116   for (int iThread = 0; iThread < getNumWorkers(); iThread++) {
117     m_vecpChildProjections[iThread] = new Projections (*m_pScanner);
118   }
119
120
121
122 }
123
124 ProjectorSupervisor::~ProjectorSupervisor()
125 {
126   for (int i = 0; i < getNumWorkers(); i++) {
127       delete m_vecpChildProjections[i];
128       m_vecpChildProjections[i] = NULL;
129     }
130
131   delete m_pScanner;
132 }
133
134 BackgroundWorkerThread*
135 ProjectorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
136 {
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);
141
142    return pThread;
143 }
144
145 void
146 ProjectorSupervisor::onDone()
147 {
148   wxCriticalSection doneSection;
149   wxCriticalSectionLocker critsect (doneSection);
150
151   Projections* pProjections = getProjections();
152   pProjections->setRemark (m_strLabel.mb_str(wxConvUTF8));
153   pProjections->setCalcTime (getTimerEnd());
154
155   wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
156   wxString msg (m_strLabel);
157   msg += _T("\n");
158   eventLog.SetString( msg );
159   wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
160
161   wxCommandEvent newProjEvent (wxEVT_COMMAND_MENU_SELECTED, NEW_PROJECTIONFILE_EVENT);
162   newProjEvent.SetClientData (pProjections);
163   wxPostEvent (theApp->getMainFrame(), newProjEvent);
164
165   setDone();
166 }
167
168
169 Projections*
170 ProjectorSupervisor::getProjections()
171 {
172   Projections* pProjections = new Projections (*m_pScanner);
173
174   int iGlobalView = 0;
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);
184     }
185   }
186
187   return (pProjections);
188 }
189
190
191 /////////////////////////////////////////////////////////////////////
192 //
193 // Class ProjectorWorker -- A worker thread
194 //
195 /////////////////////////////////////////////////////////////////////
196
197 void
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)
202 {
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;
212 }
213
214 wxThread::ExitCode
215 ProjectorWorker::Entry ()
216 {
217   const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
218   bool bFail = m_pScanner->fail();
219   wxString failMsg;
220   if (bFail) {
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 );
226   }
227   else
228   {
229     wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
230     for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
231       if (TestDestroy()) {
232 #ifdef DEBUG
233         if (theApp->getVerboseLogging()) {
234           wxString msg;
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 );
239         }
240 #endif
241         break;
242       }
243       m_pScanner->collectProjections (*m_pProjections, rPhantom, iUnit + m_iStartUnit, 1,
244         m_iOffsetView, iUnit, Trace::TRACE_NONE);
245       m_pSupervisor->onWorkerUnitTick();
246     }
247   }
248
249   if (bFail) {
250     m_pSupervisor->onWorkerFail (m_iThread, failMsg);
251   } else {
252     m_pSupervisor->onWorkerDone (m_iThread);
253   }
254
255   while (! TestDestroy())
256     Sleep(100);
257
258   return reinterpret_cast<wxThread::ExitCode>(0);
259 }
260
261 void
262 ProjectorWorker::OnExit ()
263 {
264 }
265
266 #endif // HAVE_WXTHREADS