r582: no message
[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-2001 Kevin Rosenberg
11 **
12 **  $Id: threadproj.cpp,v 1.1 2001/02/25 10:52:55 kevin Exp $
13 **
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.
17 **
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.
22 **
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 ******************************************************************************/
27
28 #include "wx/wxprec.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/wx.h"
32 #endif
33
34 #include "ct.h"
35 #include "ctsim.h"
36 #include "docs.h"
37 #include "views.h"
38 #include "threadproj.h"
39 #include "backgroundmgr.h"
40 #include "backgroundsupr.h"
41
42 #if defined(HAVE_CONFIG_H)
43 #include "config.h"
44 #endif
45
46
47
48 /////////////////////////////////////////////////////////////////////
49 //
50 // Class ProjectorSupervisorThread -- Thread for Background Supervisor
51 //
52 /////////////////////////////////////////////////////////////////////
53
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),
60   SupervisorThread()
61 {
62 }
63
64 wxThread::ExitCode
65 ProjectorSupervisorThread::Entry()
66 {
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());
69
70   projSupervisor.start();
71   while (! projSupervisor.isDone() && ! projSupervisor.fail()) {
72     Sleep(50);
73     Yield();
74   }
75   if (projSupervisor.fail())
76   {
77     wxString msg ("Error starting Projector supervisor: ");
78     msg += projSupervisor.getFailMessage().c_str();
79     msg += "\n";
80     wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
81     eventLog.SetString( msg );
82     wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
83   }
84
85   while (! projSupervisor.workersDeleted()) {
86     Sleep(50);
87     projSupervisor.ProcessPendingEvents();
88   }
89
90   return reinterpret_cast<wxThread::ExitCode>(0);
91 }
92
93 void
94 ProjectorSupervisorThread::OnExit()
95 {
96 }
97
98
99 /////////////////////////////////////////////////////////////////////
100 //
101 // Class ProjectorSupervisor -- A Background Supervisor
102 //
103 /////////////////////////////////////////////////////////////////////
104
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)
113 {
114   m_vecpChildProjections.reserve (getNumWorkers());
115   for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
116     m_vecpChildProjections[iThread] = new Projections (m_iNDet, m_iNView);    
117   }
118
119 }
120
121 ProjectorSupervisor::~ProjectorSupervisor()
122 {
123   for (int i = 0; i < getNumWorkers(); i++) {
124       delete m_vecpChildProjections[i];
125       m_vecpChildProjections[i] = NULL;
126     }
127 }
128
129 BackgroundWorkerThread*
130 ProjectorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
131 {
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);
135
136    return pThread;
137 }
138
139 void
140 ProjectorSupervisor::onDone()
141 {
142   wxCriticalSection doneSection;
143   wxCriticalSectionLocker critsect (doneSection);
144
145   ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
146   if (! pProjDoc) {
147     sys_error (ERR_SEVERE, "Unable to create projection file");
148     return;
149   }
150     
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);
160   }
161   *theApp->getLog() << m_pszLabel << "\n";
162   pProjections->setRemark (m_pszLabel);
163   pProjections->setCalcTime (getTimerEnd());
164
165   setDone();
166 }
167
168
169 Projections*
170 ProjectorSupervisor::getProjections()
171 {
172   Projections* pProjections = new Projections (m_iNDet, m_iNView);
173 #if 0
174   ImageFileArray pArray = pImageFile->getArray();
175   
176   int i;
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];
182   }
183 #endif
184   return (pProjections);
185 }
186
187
188 /////////////////////////////////////////////////////////////////////
189 //
190 // Class ProjectorWorker -- A worker thread
191 //
192 /////////////////////////////////////////////////////////////////////
193
194 void
195 ProjectorWorker::SetParameters (PhantomFileView* pPhantomView, Projections* pProjections, int iNDet, int iView,
196  const char* pszGeometry, int iNSample, double dRotation, double dFocalLength, double dViewRatio,
197  double dScanRatio)
198 {
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;
206 }
207
208 wxThread::ExitCode
209 ProjectorWorker::Entry ()
210 {
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);
214
215   bool bFail = pScanner->fail();
216   wxString failMsg;
217   if (bFail) {
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 );
223   }
224   else
225   {
226     wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
227     for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
228       if (TestDestroy()) {
229 #ifdef DEBUG
230         if (theApp->getVerboseLogging()) {
231           wxString msg;
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 ); 
236         }
237 #endif
238         break;
239       }
240       pScanner->collectProjections (*m_pProjections, rPhantom, iUnit + m_iStartUnit, 1, true, Trace::TRACE_NONE);
241       wxPostEvent (m_pSupervisor, eventProgress);
242     }
243   }
244   delete pScanner;
245
246   if (bFail) {
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);
251   } else {
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);
255   }
256
257   while (! TestDestroy())
258     Sleep(100);
259
260   return reinterpret_cast<wxThread::ExitCode>(0);
261 }
262
263 void
264 ProjectorWorker::OnExit ()
265 {
266 }