From 0730f9f3adbf326b9d4bac754634399ad688efd1 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Thu, 22 Feb 2001 11:05:38 +0000 Subject: [PATCH] r571: no message --- ChangeLog | 8 +- doc/ctsim.prj | 6 +- include/timer.h | 7 +- libctsupport/interpolator.cpp | 10 +- msvc/ctsim/ctsim.plg | 27 +++- src/ctsim.cpp | 16 +- src/ctsim.h | 16 +- src/dialogs.cpp | 7 +- src/dlgprojections.cpp | 7 +- src/dlgreconstruct.cpp | 7 +- src/docs.cpp | 39 ++++- src/docs.h | 14 +- src/graph3dview.cpp | 7 +- src/threadrecon.cpp | 291 ++++++++++++++++++++++++++++++++++ src/threadrecon.h | 115 ++++++++++++++ src/tips.cpp | 11 +- src/views.cpp | 185 +++++++++++++++++---- src/views.h | 9 +- 18 files changed, 677 insertions(+), 105 deletions(-) create mode 100644 src/threadrecon.cpp create mode 100644 src/threadrecon.h diff --git a/ChangeLog b/ChangeLog index 67bcdc7..00f074d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,15 @@ -3.0.4 - Released +3.1.0 - Released * ctsim: Added "Verbose Logging" and "Startup Tips" options to Preferences. * ctsim: Added tips to be displayed at startup and via the help menu. + + * ctsim: Added accelerator key for File-Properties + + * ctsim: Added threaded reconstructions for background + processing as well as taking advantage of multiple-CPU's + on SMP systems. 3.0.3 - Released 2/20/01 diff --git a/doc/ctsim.prj b/doc/ctsim.prj index 11ca2c4..d9dd4ae 100644 --- a/doc/ctsim.prj +++ b/doc/ctsim.prj @@ -9,6 +9,9 @@ ctsim.tex 0 +ctsim-gui.tex +TeX +268447738 0 207 31 207 1 176 176 1253 763 mytitle.sty DATA 273679026 0 9 1 8 22 66 66 1143 653 @@ -24,9 +27,6 @@ TeX ctsim-appendix.tex TeX 268447738 0 12 1 0 1 44 44 1121 631 -ctsim-gui.tex -TeX -268447738 0 175 7 175 8 176 176 1253 763 ctsim.tex TeX 402665466 0 25 31 27 37 22 22 1099 609 diff --git a/include/timer.h b/include/timer.h index e938ae9..226d258 100644 --- a/include/timer.h +++ b/include/timer.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: timer.h,v 1.6 2001/01/28 19:10:18 kevin Exp $ +** $Id: timer.h,v 1.7 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -25,6 +25,10 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ +#ifndef _TIMER_H +#define _TIMER_H + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -187,5 +191,6 @@ class TimerCollectiveMPI : public TimerMPI #endif +#endif // _TIMER_H diff --git a/libctsupport/interpolator.cpp b/libctsupport/interpolator.cpp index e8abdfa..bbc7f27 100644 --- a/libctsupport/interpolator.cpp +++ b/libctsupport/interpolator.cpp @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: interpolator.cpp,v 1.1 2001/02/11 21:57:08 kevin Exp $ +** $Id: interpolator.cpp,v 1.2 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -42,13 +42,17 @@ CubicPolyInterpolator::interpolate (double x) int hi = lo + 3; if (lo < -1) { +#ifdef DEBUG sys_error (ERR_WARNING, "x=%f, out of range [CubicPolyInterpolator]", x); +#endif return (0); } else if (lo == -1) // linear interpolate at between x = 0 & 1 return m_pdY[0] + x * (m_pdY[1] - m_pdY[0]); if (hi > m_n) { +#ifdef DEBUG sys_error (ERR_WARNING, "x=%f, out of range [CubicPolyInterpolator]", x); +#endif return (0); } else if (hi == m_n) {// linear interpolate between x = (n-2) and (n-1) double frac = x - (lo + 1); @@ -116,7 +120,9 @@ CubicSplineInterpolator::interpolate (double x) int hi = lo + 1; if (lo < 0 || hi >= m_n) { - sys_error (ERR_SEVERE, "X range out of bounds [CubicSplineInterpolator::interpolate]"); +#ifdef DEBUG + sys_error (ERR_SEVERE, "x out of bounds [CubicSplineInterpolator::interpolate]"); +#endif return (0); } diff --git a/msvc/ctsim/ctsim.plg b/msvc/ctsim/ctsim.plg index f240cfc..6fdda36 100644 --- a/msvc/ctsim/ctsim.plg +++ b/msvc/ctsim/ctsim.plg @@ -6,19 +6,23 @@ --------------------Configuration: ctsim - Win32 Debug--------------------

Command Lines

-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE7.tmp" with contents +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E6.tmp" with contents [ /nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "\wx2.2.5\include" /I "..\..\..\fftw-2.1.3\fftw" /I "\wx2.2.5\src\png" /I "\wx2.2.5\src\zlib" /I "..\..\include" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\rfftw" /D VERSION=\"3.0.0beta1\" /D "_DEBUG" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D CTSIMVERSION=\"3.0.4\" /D CTSIMVERSION=\"3.0.0alpha5\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c "C:\ctsim\src\ctsim.cpp" +"C:\ctsim\src\dialogs.cpp" +"C:\ctsim\src\docs.cpp" +"C:\ctsim\src\views.cpp" ] -Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE7.tmp" -Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE8.tmp" with contents +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E6.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E7.tmp" with contents [ /nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "\wx2.2.5\include" /I "..\..\..\fftw-2.1.3\fftw" /I "\wx2.2.5\src\png" /I "\wx2.2.5\src\zlib" /I "..\..\include" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\rfftw" /D VERSION=\"3.0.0beta1\" /D "_DEBUG" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D CTSIMVERSION=\"3.0.4\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c -"C:\ctsim\src\tips.cpp" +"C:\ctsim\src\graph3dview.cpp" +"C:\ctsim\src\threadrecon.cpp" ] -Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE8.tmp" -Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE9.tmp" with contents +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E7.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E8.tmp" with contents [ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" .\Debug\ctsim.obj @@ -30,6 +34,7 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\.. .\Debug\views.obj .\Debug\ctsim.res .\Debug\tips.obj +.\Debug\threadrecon.obj \ctsim\msvc\libctsim\Debug\libctsim.lib "\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib" "\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib" @@ -40,12 +45,18 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\.. \wx2.2.5\lib\zlibd.lib \wx2.2.5\lib\tiffd.lib ] -Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSPE9.tmp" +Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP3E8.tmp"

Output Window

Compiling... ctsim.cpp +docs.cpp +Skipping... (no relevant changes detected) +dialogs.cpp +views.cpp Compiling... -tips.cpp +threadrecon.cpp +Skipping... (no relevant changes detected) +graph3dview.cpp Linking... diff --git a/src/ctsim.cpp b/src/ctsim.cpp index 510e248..1155aac 100644 --- a/src/ctsim.cpp +++ b/src/ctsim.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ctsim.cpp,v 1.86 2001/02/22 00:56:50 kevin Exp $ +** $Id: ctsim.cpp,v 1.87 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -29,13 +29,8 @@ #define strdup _strdup #endif -// For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif @@ -73,7 +68,7 @@ #endif #endif -static const char* rcsindent = "$Id: ctsim.cpp,v 1.86 2001/02/22 00:56:50 kevin Exp $"; +static const char* rcsindent = "$Id: ctsim.cpp,v 1.87 2001/02/22 11:05:38 kevin Exp $"; struct option CTSimApp::ctsimOptions[] = { @@ -335,6 +330,7 @@ EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout) EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents) EVT_MENU(MAINMENU_HELP_TIPS, MainFrame::OnHelpTips) EVT_MENU(IDH_QUICKSTART, MainFrame::OnHelpButton) +EVT_MENU(MAINMENU_LOG_EVENT, MainFrame::OnLogEvent) EVT_BUTTON(IDH_DLG_RASTERIZE, MainFrame::OnHelpButton) EVT_BUTTON(IDH_DLG_PROJECTIONS, MainFrame::OnHelpButton) EVT_BUTTON(IDH_DLG_RECONSTRUCTION, MainFrame::OnHelpButton) @@ -583,6 +579,12 @@ CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vectorgetLog() << event.GetString(); +} + void MainFrame::OnHelpTips (wxCommandEvent& event) { diff --git a/src/ctsim.h b/src/ctsim.h index a2c2afa..9768970 100644 --- a/src/ctsim.h +++ b/src/ctsim.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ctsim.h,v 1.50 2001/02/22 00:56:50 kevin Exp $ +** $Id: ctsim.h,v 1.51 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -139,6 +139,7 @@ public: void OnHelpTips (wxCommandEvent& event); void OnCreatePhantom (wxCommandEvent& event); void OnPreferences (wxCommandEvent& event); + void OnLogEvent (wxCommandEvent& event); // used by thread children void OnHelpButton (wxCommandEvent& event); @@ -224,7 +225,9 @@ public: { return m_docManager; } wxString getUntitledFilename(); - + + int getNumberCPU() const { return wxThread::GetCPUCount(); } + EZPlotDialog* makeEZPlotDialog() { return new EZPlotDialog (m_pFrame); } @@ -277,11 +280,11 @@ enum { MAINMENU_HELP_SECONDARY, #endif MAINMENU_FILE_CREATE_PHANTOM, - MAINMENU_FILE_CREATE_FILTER, MAINMENU_FILE_EXIT, MAINMENU_FILE_PREFERENCES, - + MAINMENU_LOG_EVENT, + PJMENU_FILE_PROPERTIES, PJMENU_RECONSTRUCT_FBP, PJMENU_RECONSTRUCT_FOURIER, @@ -334,7 +337,8 @@ enum { PHMMENU_FILE_PROPERTIES, PHMMENU_PROCESS_RASTERIZE, PHMMENU_PROCESS_PROJECTIONS, - + + PLOTMENU_FILE_PROPERTIES, PLOTMENU_VIEW_SCALE_MINMAX, PLOTMENU_VIEW_SCALE_AUTO, PLOTMENU_VIEW_SCALE_FULL, @@ -346,6 +350,8 @@ enum { GRAPH3D_VIEW_SCALE_AUTO, GRAPH3D_VIEW_SCALE_MINMAX, GRAPH3D_VIEW_SCALE_FULL, + + RECONSTRUCTION_THREAD_EVENT, }; #endif diff --git a/src/dialogs.cpp b/src/dialogs.cpp index 9915a34..8e25338 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: dialogs.cpp,v 1.39 2001/02/22 00:56:50 kevin Exp $ +** $Id: dialogs.cpp,v 1.40 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -29,13 +29,8 @@ // #pragma implementation #endif -// For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif diff --git a/src/dlgprojections.cpp b/src/dlgprojections.cpp index e2d3a44..76b0ae4 100644 --- a/src/dlgprojections.cpp +++ b/src/dlgprojections.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: dlgprojections.cpp,v 1.22 2001/01/30 05:05:41 kevin Exp $ +** $Id: dlgprojections.cpp,v 1.23 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -29,13 +29,8 @@ #pragma implementation "dlgprojections.h" #endif -// For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/utils.h" #include "wx/frame.h" diff --git a/src/dlgreconstruct.cpp b/src/dlgreconstruct.cpp index 9f1b950..093586b 100644 --- a/src/dlgreconstruct.cpp +++ b/src/dlgreconstruct.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: dlgreconstruct.cpp,v 1.17 2001/02/20 04:48:45 kevin Exp $ +** $Id: dlgreconstruct.cpp,v 1.18 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -29,13 +29,8 @@ #pragma implementation "dlgreconstruct.h" #endif -// For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #include "wx/utils.h" #include "wx/frame.h" #include "wx/button.h" diff --git a/src/docs.cpp b/src/docs.cpp index 93c5f1e..460082a 100644 --- a/src/docs.cpp +++ b/src/docs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: docs.cpp,v 1.24 2001/02/21 20:13:03 kevin Exp $ +** $Id: docs.cpp,v 1.25 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -29,18 +29,14 @@ // #pragma implementation #endif -// For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/txtstrm.h" #include "wx/file.h" +#include "wx/thread.h" #if !wxUSE_DOC_VIEW_ARCHITECTURE #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! @@ -50,6 +46,8 @@ #include "ctsim.h" #include "docs.h" #include "views.h" +#include "threadrecon.h" + // ImageFileDocument @@ -145,6 +143,35 @@ ProjectionFileDocument::OnSaveDocument(const wxString& filename) return true; } +ProjectionFileDocument::~ProjectionFileDocument() +{ + for (int i = 0; i < m_vecpActiveReconstructors.size(); i++) { + ThreadedReconstructor* pThreadedReconstructor = m_vecpActiveReconstructors[i]; + if (pThreadedReconstructor) { + pThreadedReconstructor->cancel(); + } + } + + delete m_pProjectionFile; +} + +void +ProjectionFileDocument::addReconstructor (ThreadedReconstructor* pRecon) +{ + wxCriticalSectionLocker locker (m_criticalSection); + m_vecpActiveReconstructors.push_back (pRecon); +} + +void +ProjectionFileDocument::removeReconstructor (ThreadedReconstructor* pRecon) +{ + wxCriticalSectionLocker locker (m_criticalSection); + for (int i = 0; i < m_vecpActiveReconstructors.size(); i++) { + if (m_vecpActiveReconstructors[i] == pRecon) + m_vecpActiveReconstructors[i] = NULL; + } +} + bool ProjectionFileDocument::OnOpenDocument(const wxString& filename) { diff --git a/src/docs.h b/src/docs.h index e7b6815..88e362e 100644 --- a/src/docs.h +++ b/src/docs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: docs.h,v 1.21 2001/02/02 00:46:38 kevin Exp $ +** $Id: docs.h,v 1.22 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -39,6 +39,7 @@ #include "phantom.h" #include "projections.h" #include "plotfile.h" +#include "threadrecon.h" class ProjectionFileView; class PhantomFileView; @@ -92,7 +93,9 @@ private: DECLARE_DYNAMIC_CLASS(ProjectionFileDocument) Projections* m_pProjectionFile; bool m_bBadFileOpen; - + std::vector m_vecpActiveReconstructors; + wxCriticalSection m_criticalSection; + public: virtual bool OnSaveDocument (const wxString& filename); virtual bool OnOpenDocument (const wxString& filename); @@ -105,10 +108,7 @@ public: m_pProjectionFile = new Projections; } - virtual ~ProjectionFileDocument () - { - delete m_pProjectionFile; - } + virtual ~ProjectionFileDocument (); const Projections& getProjections () const { return *m_pProjectionFile; } Projections& getProjections () { return *m_pProjectionFile; } @@ -121,6 +121,8 @@ public: ProjectionFileView* getView() const; bool getBadFileOpen() const { return m_bBadFileOpen; } void setBadFileOpen() { m_bBadFileOpen = true; } + void addReconstructor (ThreadedReconstructor* pRecon); + void removeReconstructor (ThreadedReconstructor* pRecon); }; diff --git a/src/graph3dview.cpp b/src/graph3dview.cpp index 7abec42..55fe7c1 100644 --- a/src/graph3dview.cpp +++ b/src/graph3dview.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: graph3dview.cpp,v 1.14 2001/02/20 22:11:27 kevin Exp $ +** $Id: graph3dview.cpp,v 1.15 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -30,13 +30,8 @@ #pragma interface #endif -// For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif diff --git a/src/threadrecon.cpp b/src/threadrecon.cpp new file mode 100644 index 0000000..aa9a7bb --- /dev/null +++ b/src/threadrecon.cpp @@ -0,0 +1,291 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: threadrecon.cpp +** Purpose: Threaded reconstruction class +** Programmer: Kevin Rosenberg +** Date Started: February 2001 +** +** This is part of the CTSim program +** Copyright (C) 1983-2001 Kevin Rosenberg +** +** $Id: threadrecon.cpp,v 1.1 2001/02/22 11:05:38 kevin Exp $ +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License (version 2) as +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#include "ct.h" +#include "ctsim.h" +#include "docs.h" +#include "views.h" +#include "threadrecon.h" + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + + +IMPLEMENT_DYNAMIC_CLASS(ThreadedReconstructor, wxEvtHandler) +BEGIN_EVENT_TABLE(ThreadedReconstructor, wxEvtHandler) +EVT_MENU(RECONSTRUCTION_THREAD_EVENT, ThreadedReconstructor::OnThreadEvent) +END_EVENT_TABLE() + + +enum { + RTHREAD_UNIT_COMPLETE = -1, + RTHREAD_THREAD_DONE = -2, + RTHREAD_THREAD_CANCELLED = -3, +}; + +ThreadedReconstructor::ThreadedReconstructor (ProjectionFileView* pProjView, + int iImageNX, int iImageNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, + int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam, + const char* pszBackprojectName, const char* const pszLabel) + : m_pProjView(pProjView), m_pDialogProgress(NULL), m_bFail(false), m_iNumThreads(0), m_iImageNX(iImageNX), + m_iImageNY(iImageNY), m_strLabel(pszLabel), m_pTimer(NULL), m_bCancelled(false), m_bCancelling(false), + m_bDone(false), wxEvtHandler() +{ + m_iNumThreads = theApp->getNumberCPU(); +// ++m_iNumThreads; + m_iTotalViews = m_pProjView->GetDocument()->getProjections().nView(); + int iBaseViews = m_iTotalViews / m_iNumThreads; + int iExtraViews = m_iTotalViews % m_iNumThreads; + + m_vecpChildImageFile.reserve (m_iNumThreads); + m_vecpReconstructor.reserve (m_iNumThreads); + m_vecpThread.reserve (m_iNumThreads); + + for (unsigned int iProc = 0; iProc < m_iNumThreads; iProc++) { + m_vecpChildImageFile[iProc] = new ImageFile (iImageNX, iImageNY); + m_vecpReconstructor[iProc] = new Reconstructor (m_pProjView->GetDocument()->getProjections(), *m_vecpChildImageFile[iProc], + pszFilterName, dFilterParam, pszFilterMethod, iZeropad, pszFilterGenerationName, + pszInterpName, iInterpParam, pszBackprojectName, Trace::TRACE_NONE); + + int iStartView = iProc * iBaseViews; + int iNumViews = iBaseViews; + if (iProc < iExtraViews) + ++iNumViews; + m_vecpThread[iProc] = new ReconstructionThread (this, m_vecpReconstructor[iProc], iProc, iStartView, iNumViews); + if (m_vecpThread[iProc]->Create () != wxTHREAD_NO_ERROR) { + m_bFail = true; + break; + } + } + + m_pProjView->GetDocument()->addReconstructor (this); + // m_pDialogProgress = new wxProgressDialog (_T("Filtered Backprojection"), _T("Reconstruction Progress"), m_iTotalViews, pProjView->getFrame(), wxPD_CAN_ABORT | wxPD_AUTO_HIDE); +} + + +bool +ThreadedReconstructor::start() +{ + if (m_bFail) + return false; + + // starting all threads + m_iRunning = m_iNumThreads; + m_iViewsDone = 0; + m_pTimer = new Timer; +// theApp->addBackgroundTask (this, m_iTotalViews); + + int i; + for (i = 0; i < m_iNumThreads; i++) + m_vecpThread[i]->Run(); + + + if (m_bCancelled) + return false; + + return true; +} + +void +ThreadedReconstructor::cancel() +{ + if (m_bCancelled) + return; + + wxCriticalSectionLocker locker (m_criticalSection); + + for (int i = 0; i < m_iNumThreads; i++) + if (m_vecpThread[i]) + m_vecpThread[i]->Delete(); + + for (i = 0; i < m_iNumThreads; i++) + delete m_vecpReconstructor[i]; + + m_iNumThreads = 0; + m_iRunning = 0; + delete m_pDialogProgress; + delete m_pTimer; + m_pDialogProgress = NULL; + m_pProjView->GetDocument()->removeReconstructor (this); + m_bCancelled = true; + m_bDone = true; + // theApp->removeBackgroundTask (this); +} + +void +ThreadedReconstructor::onDone() +{ + for (int i = 0; i < m_iNumThreads; i++) + delete m_vecpReconstructor[i]; + + m_pProjView->GetDocument()->removeReconstructor (this); + ImageFileDocument* pReconDoc = theApp->newImageDoc(); + if (! pReconDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } + + ImageFile* pImageFile = getImageFile(); + pReconDoc->setImageFile (pImageFile); + if (theApp->getAskDeleteNewDocs()) + pReconDoc->Modify (true); + pReconDoc->UpdateAllViews (m_pProjView); + if (ImageFileView* rasterView = pReconDoc->getView()) { + rasterView->OnUpdate (rasterView, NULL); + rasterView->getFrame()->SetFocus(); + rasterView->getFrame()->Show(true); + } + *theApp->getLog() << m_strLabel << "\n"; + pImageFile->labelAdd (m_pProjView->GetDocument()->getProjections().getLabel()); + pImageFile->labelAdd (m_strLabel.c_str(), m_pTimer->timerEnd()); + delete m_pTimer; + + wxIdleEvent event; + theApp->OnIdle(event); + m_bDone = true; + // theApp->removeBackgroundTask (this); + // delete this; +} + + +void +ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event) +{ + if (m_bCancelling) { + cancel(); + return; + } + + wxCriticalSectionLocker locker (m_criticalSection); + + int iEventId = event.GetInt(); + if (iEventId == RTHREAD_UNIT_COMPLETE) { + ++m_iViewsDone; + *theApp->getLog() << "Views done: " << static_cast(m_iViewsDone) <<"\n"; + + if (m_pDialogProgress) + m_bCancelling = ! m_pDialogProgress->Update (m_iViewsDone - 1); + + // m_bCancelling = theApp->updateBackgroundTask (this, m_iViewsDone); + if (m_iViewsDone == m_iTotalViews) { + delete m_pDialogProgress; + m_pDialogProgress = NULL; + onDone(); + } + if (m_bCancelling) { + cancel(); + return; + } + } + else if (event.GetInt() >= 0) { + m_iRunning--; + m_vecpThread[event.GetInt()] = NULL; + *theApp->getLog() << "Thread finished. Remaining threads: " << m_iRunning << "\n"; + } + else + *theApp->getLog() << "Got event #" << iEventId << "\n"; + +} + +ImageFile* +ThreadedReconstructor::getImageFile() const +{ + ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY); + pImageFile->arrayDataClear(); + ImageFileArray pArray = pImageFile->getArray(); + + int i; + for (i = 0; i < m_iNumThreads; i++) { + ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray(); + for (int ix = 0; ix < m_iImageNX; ix++) + for (int iy = 0; iy < m_iImageNY; iy++) + pArray[ix][iy] += pChildArray[ix][iy]; + } + + for (i = 0; i < m_iNumThreads; i++) { + delete m_vecpChildImageFile[i]; +// m_vecpChildImageFile[i] = NULL; + } + + return (pImageFile); +} + +bool +ThreadedReconstructor::testDone() +{ + return (m_iRunning <= 0 ? true : false); +} + + +ThreadedReconstructor::~ThreadedReconstructor() +{ +} + + +ReconstructionThread::ReconstructionThread (ThreadedReconstructor* pSupervisor, + Reconstructor* pReconstructor, int iThread, int iStartView, int iNumViews) +: m_pSupervisor(pSupervisor), m_pReconstructor(pReconstructor), + m_iStartView(iStartView), m_iNumViews(iNumViews), m_iThread(iThread), + wxThread(wxTHREAD_DETACHED) +{ +} + +wxThread::ExitCode +ReconstructionThread::Entry () +{ + wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, RECONSTRUCTION_THREAD_EVENT); + for (int iView = 0; iView < m_iNumViews; iView++) { + if (TestDestroy()) { + wxString msg; + msg.Printf("TestDestroy TRUE at view #%d\n", iView); + wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT ); + event.SetString( msg ); + wxPostEvent( theApp->getMainFrame(), event ); // send in a thread-safe way + return reinterpret_cast(RTHREAD_THREAD_CANCELLED); + } + m_pReconstructor->reconstructView (iView + m_iStartView, 1); + eventProgress.SetInt (RTHREAD_UNIT_COMPLETE); + wxPostEvent (m_pSupervisor, eventProgress); + } + + eventProgress.SetInt (m_iThread); // Send back thread# that has finished + wxPostEvent (m_pSupervisor, eventProgress); + + return reinterpret_cast(0); +} + +void +ReconstructionThread::OnExit () +{ +} diff --git a/src/threadrecon.h b/src/threadrecon.h new file mode 100644 index 0000000..53368fa --- /dev/null +++ b/src/threadrecon.h @@ -0,0 +1,115 @@ +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: threadrecon.h +** Purpose: Header file for thread reconstructions +** Programmer: Kevin Rosenberg +** Date Started: February 2001 +** +** This is part of the CTSim program +** Copyright (C) 1983-2001 Kevin Rosenberg +** +** $Id: threadrecon.h,v 1.1 2001/02/22 11:05:38 kevin Exp $ +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License (version 2) as +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +#ifndef _THREADRECON_H +#define _THREADRECON_H + +#include +#include +#include +#include "timer.h" + + +class Reconstructor; +class ImageFile; +class ProjectionFileDocument; +class ReconstructionThread; +class ProjectionFileView; + +class ThreadedReconstructor : public wxEvtHandler { +private: + DECLARE_DYNAMIC_CLASS(ThreadedReconstructor) + + std::vector m_vecpReconstructor; + std::vector m_vecpChildImageFile; + std::vector m_vecpThread; + ProjectionFileView* m_pProjView; + wxProgressDialog* m_pDialogProgress; + + volatile bool m_bFail; + int m_iNumThreads; + const int m_iImageNX; + const int m_iImageNY; + volatile int m_iRunning; + volatile unsigned int m_iViewsDone; + volatile unsigned int m_iTotalViews; + wxCriticalSection m_criticalSection; + wxString m_strLabel; + Timer* m_pTimer; + bool m_bCancelled; + bool m_bCancelling; + bool m_bDone; + +public: + ThreadedReconstructor (ProjectionFileView* pProjView, + int iNX, int iNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, + int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam, + const char* pszBackprojectName, const char* const pszLabel); + + ThreadedReconstructor () + : m_bFail(true), m_iNumThreads(0), m_iImageNX(0), m_iImageNY(0), m_iTotalViews(0) + {} + + ~ThreadedReconstructor (); + + void OnThreadEvent (wxCommandEvent& event); + bool testDone(); + void cancel(); + + void onDone(); + bool start(); + bool fail() const {return m_bFail;} + bool getDone() const {return m_bDone;} + + ImageFile* getImageFile() const; + + DECLARE_EVENT_TABLE() +}; + + + +class ReconstructionThread : public wxThread { +private: + ThreadedReconstructor* m_pSupervisor; + Reconstructor* m_pReconstructor; + int m_iStartView; + int m_iNumViews; + int m_iThread; + +public: + ReconstructionThread (ThreadedReconstructor* pSupervisor, Reconstructor* pReconstructor, + int iThread, int iStartView, int iNumViews); + + virtual wxThread::ExitCode Entry(); // thread execution starts here + + // called when the thread exits - whether it terminates normally or is + // stopped with Delete() (but not when it is Kill()ed!) + virtual void OnExit(); +}; + + +#endif diff --git a/src/tips.cpp b/src/tips.cpp index c263b48..dc425d6 100644 --- a/src/tips.cpp +++ b/src/tips.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2001 Kevin Rosenberg ** -** $Id: tips.cpp,v 1.1 2001/02/22 00:56:50 kevin Exp $ +** $Id: tips.cpp,v 1.2 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -25,17 +25,8 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ -#ifdef MSVC -#define strdup _strdup -#endif - -// For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif diff --git a/src/views.cpp b/src/views.cpp index c20009d..60eda6a 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: views.cpp,v 1.111 2001/02/22 00:56:50 kevin Exp $ +** $Id: views.cpp,v 1.112 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -25,13 +25,7 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ -// For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif @@ -53,6 +47,9 @@ #include "backprojectors.h" #include "reconstruct.h" #include "timer.h" +#include "threadrecon.h" + +#define CTSIM_THREADS 1 #if defined(MSVC) || HAVE_SSTREAM #include @@ -835,7 +832,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_REVERT, "Re&vert"); m_pFileMenu->AppendSeparator(); - m_pFileMenu->Append(IFMENU_FILE_PROPERTIES, "P&roperties"); + m_pFileMenu->Append(IFMENU_FILE_PROPERTIES, "P&roperties\tCtrl-I"); m_pFileMenu->Append(IFMENU_FILE_EXPORT, "&Export..."); m_pFileMenu->AppendSeparator(); @@ -928,15 +925,16 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) subframe->Centre(wxBOTH); - wxAcceleratorEntry accelEntries[4]; + wxAcceleratorEntry accelEntries[5]; accelEntries[0].Set (wxACCEL_CTRL, static_cast('A'), IFMENU_VIEW_SCALE_AUTO); accelEntries[1].Set (wxACCEL_CTRL, static_cast('U'), IFMENU_VIEW_SCALE_FULL); accelEntries[2].Set (wxACCEL_CTRL, static_cast('E'), IFMENU_VIEW_SCALE_MINMAX); + accelEntries[3].Set (wxACCEL_CTRL, static_cast('I'), IFMENU_FILE_PROPERTIES); #if wxUSE_GLCANVAS - accelEntries[3].Set (wxACCEL_CTRL, static_cast('3'), IFMENU_IMAGE_CONVERT3D); - wxAcceleratorTable accelTable (4, accelEntries); + accelEntries[4].Set (wxACCEL_CTRL, static_cast('3'), IFMENU_IMAGE_CONVERT3D); + wxAcceleratorTable accelTable (5, accelEntries); #else - wxAcceleratorTable accelTable (3, accelEntries); + wxAcceleratorTable accelTable (4, accelEntries); #endif subframe->SetAcceleratorTable (accelTable); @@ -1920,7 +1918,7 @@ PhantomFileView::OnProjections (wxCommandEvent& event) } } } else { - wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), pProj->nView() + 1, getFrameForChild(), wxPD_CAN_ABORT); + wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), pProj->nView() + 1, getFrameForChild(), wxPD_CAN_ABORT ); for (int i = 0; i < pProj->nView(); i++) { theScanner.collectProjections (*pProj, rPhantom, i, 1, true, m_iDefaultTrace); if (! dlgProgress.Update (i+1)) { @@ -1991,7 +1989,7 @@ PhantomFileView::OnRasterize (wxCommandEvent& event) pImageFile->setArraySize (m_iDefaultRasterNX, m_iDefaultRasterNY); wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), - pImageFile->nx() + 1, getFrameForChild(), wxPD_CAN_ABORT); + pImageFile->nx() + 1, getFrameForChild(), wxPD_CAN_ABORT ); Timer timer; for (unsigned int i = 0; i < pImageFile->nx(); i++) { rPhantom.convertToImagefile (*pImageFile, m_dDefaultRasterViewRatio, m_iDefaultRasterNSamples, @@ -2065,7 +2063,7 @@ PhantomFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_CLOSE, "&Close"); m_pFileMenu->AppendSeparator(); - m_pFileMenu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties"); + m_pFileMenu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties\tCtrl-I"); m_pFileMenu->AppendSeparator(); m_pFileMenu->Append(wxID_PRINT, "&Print..."); @@ -2098,10 +2096,11 @@ PhantomFileView::CreateChildFrame(wxDocument *doc, wxView *view) subframe->SetMenuBar(menu_bar); subframe->Centre(wxBOTH); - wxAcceleratorEntry accelEntries[2]; + wxAcceleratorEntry accelEntries[3]; accelEntries[0].Set (wxACCEL_CTRL, static_cast('J'), PHMMENU_PROCESS_PROJECTIONS); accelEntries[1].Set (wxACCEL_CTRL, static_cast('R'), PHMMENU_PROCESS_RASTERIZE); - wxAcceleratorTable accelTable (2, accelEntries); + accelEntries[2].Set (wxACCEL_CTRL, static_cast('I'), PHMMENU_FILE_PROPERTIES); + wxAcceleratorTable accelTable (3, accelEntries); subframe->SetAcceleratorTable (accelTable); return subframe; @@ -2218,6 +2217,7 @@ IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView) BEGIN_EVENT_TABLE(ProjectionFileView, wxView) EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties) EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP) +EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier) EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar) EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar) END_EVENT_TABLE() @@ -2354,7 +2354,132 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event) void ProjectionFileView::OnReconstructFourier (wxCommandEvent& event) { +#if CTSIM_THREADS + DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY, + m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, + m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, + m_iDefaultTrace); + + int retVal = dialogReconstruction.ShowModal(); + if (retVal == wxID_OK) { + m_iDefaultNX = dialogReconstruction.getXSize(); + m_iDefaultNY = dialogReconstruction.getYSize(); + wxString optFilterName = dialogReconstruction.getFilterName(); + m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.c_str()); + m_dDefaultFilterParam = dialogReconstruction.getFilterParam(); + wxString optFilterMethodName = dialogReconstruction.getFilterMethodName(); + m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.c_str()); + m_iDefaultZeropad = dialogReconstruction.getZeropad(); + wxString optFilterGenerationName = dialogReconstruction.getFilterGenerationName(); + m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.c_str()); + wxString optInterpName = dialogReconstruction.getInterpName(); + m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.c_str()); + m_iDefaultInterpParam = dialogReconstruction.getInterpParam(); + wxString optBackprojectName = dialogReconstruction.getBackprojectName(); + m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str()); + m_iDefaultTrace = dialogReconstruction.getTrace(); + + if (m_iDefaultNX > 0 && m_iDefaultNY > 0) { + const Projections& rProj = GetDocument()->getProjections(); + ImageFile* pImageFile = new ImageFile; + pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY); + std::ostringstream os; + os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str(); + + Timer timerRecon; + if (m_iDefaultTrace > Trace::TRACE_CONSOLE) { + Reconstructor* pReconstructor = new Reconstructor (rProj, *pImageFile, optFilterName.c_str(), + m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), + optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace); + + ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstructor, rProj, *pImageFile, m_iDefaultTrace, getFrameForChild()); + for (int iView = 0; iView < rProj.nView(); iView++) { + ::wxYield(); + if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView, true)) { + delete pDlgReconstruct; + delete pReconstructor; + delete pImageFile; + return; + } + ::wxYield(); + ::wxYield(); + while (pDlgReconstruct->isPaused()) { + ::wxYield(); + ::wxUsleep(50); + } + } + delete pDlgReconstruct; + delete pReconstructor; + ImageFileDocument* pReconDoc = theApp->newImageDoc(); + if (! pReconDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } + pReconDoc->setImageFile (pImageFile); + if (theApp->getAskDeleteNewDocs()) + pReconDoc->Modify (true); + pReconDoc->UpdateAllViews (this); + if (ImageFileView* rasterView = pReconDoc->getView()) { + rasterView->OnUpdate (rasterView, NULL); + rasterView->getFrame()->SetFocus(); + rasterView->getFrame()->Show(true); + } + *theApp->getLog() << os.str().c_str() << "\n"; + pImageFile->labelAdd (rProj.getLabel()); + pImageFile->labelAdd (os.str().c_str(), timerRecon.timerEnd()); + + } else { +#if CTSIM_THREADS + ThreadedReconstructor* pReconstructor = new ThreadedReconstructor (this, + m_iDefaultNX, m_iDefaultNY, optFilterName.c_str(), + m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), + optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), os.str().c_str()); + if (! pReconstructor->start()) { + delete pImageFile; + delete pReconstructor; + return; + } + delete pImageFile; + // delete pReconstructor; +#else + Reconstructor* pReconstructor = new Reconstructor (rProj, *pImageFile, optFilterName.c_str(), + m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), + optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace); + + wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT ); + for (int iView = 0; iView < rProj.nView(); iView++) { + pReconstructor->reconstructView (iView, 1); + if (! dlgProgress.Update (iView + 1)) { + delete pReconstructor; + delete pImageFile; + return; + } + } + delete pReconstructor; + ImageFileDocument* pReconDoc = theApp->newImageDoc(); + if (! pReconDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } + pReconDoc->setImageFile (pImageFile); + if (theApp->getAskDeleteNewDocs()) + pReconDoc->Modify (true); + pReconDoc->UpdateAllViews (this); + if (ImageFileView* rasterView = pReconDoc->getView()) { + rasterView->OnUpdate (rasterView, NULL); + rasterView->getFrame()->SetFocus(); + rasterView->getFrame()->Show(true); + } + *theApp->getLog() << os.str().c_str() << "\n"; + pImageFile->labelAdd (rProj.getLabel()); + pImageFile->labelAdd (os.str().c_str(), timerRecon.timerEnd()); +#endif + } + } + } +#else wxMessageBox ("Fourier Reconstruction is not yet supported", "Unimplemented function"); +#endif } void @@ -2413,7 +2538,7 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event) } delete pDlgReconstruct; } else { - wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT); + wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT ); for (int iView = 0; iView < rProj.nView(); iView++) { pReconstructor->reconstructView (iView, 1); if (! dlgProgress.Update (iView + 1)) { @@ -2488,7 +2613,7 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W"); m_pFileMenu->AppendSeparator(); - m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, "P&roperties"); + m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, "P&roperties\tCtrl-I"); m_pFileMenu->AppendSeparator(); m_pFileMenu->Append(wxID_PRINT, "&Print..."); @@ -2504,13 +2629,15 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) wxMenu *convert_menu = new wxMenu; convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L"); - convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-I"); + convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-M"); wxMenu *reconstruct_menu = new wxMenu; reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R", "Reconstruct image using filtered backprojection"); reconstruct_menu->Append (PJMENU_RECONSTRUCT_FOURIER, "&Fourier...\tCtrl-E", "Reconstruct image using inverse Fourier"); +#ifndef CTSIM_THREADS reconstruct_menu->Enable (PJMENU_RECONSTRUCT_FOURIER, false); - +#endif + wxMenu *help_menu = new wxMenu; help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1"); help_menu->Append (MAINMENU_HELP_TIPS, "&Tips"); @@ -2527,12 +2654,13 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) subframe->SetMenuBar(menu_bar); subframe->Centre(wxBOTH); - wxAcceleratorEntry accelEntries[4]; + wxAcceleratorEntry accelEntries[5]; accelEntries[0].Set (wxACCEL_CTRL, static_cast('L'), PJMENU_CONVERT_POLAR); - accelEntries[1].Set (wxACCEL_CTRL, static_cast('I'), PJMENU_CONVERT_FFT_POLAR); + accelEntries[1].Set (wxACCEL_CTRL, static_cast('M'), PJMENU_CONVERT_FFT_POLAR); accelEntries[2].Set (wxACCEL_CTRL, static_cast('R'), PJMENU_RECONSTRUCT_FBP); accelEntries[3].Set (wxACCEL_CTRL, static_cast('E'), PJMENU_RECONSTRUCT_FOURIER); - wxAcceleratorTable accelTable (4, accelEntries); + accelEntries[4].Set (wxACCEL_CTRL, static_cast('I'), PJMENU_FILE_PROPERTIES); + wxAcceleratorTable accelTable (5, accelEntries); subframe->SetAcceleratorTable (accelTable); return subframe; @@ -2680,7 +2808,7 @@ PlotFileCanvas::OnDraw(wxDC& dc) IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView) BEGIN_EVENT_TABLE(PlotFileView, wxView) -EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties) +EVT_MENU(PLOTMENU_FILE_PROPERTIES, PlotFileView::OnProperties) EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax) EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto) EVT_MENU(PLOTMENU_VIEW_SCALE_FULL, PlotFileView::OnScaleFull) @@ -2813,7 +2941,7 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W"); m_pFileMenu->AppendSeparator(); - m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, "P&roperties"); + m_pFileMenu->Append(PLOTMENU_FILE_PROPERTIES, "P&roperties\tCtrl-I"); m_pFileMenu->AppendSeparator(); m_pFileMenu->Append(wxID_PRINT, "&Print..."); @@ -2847,11 +2975,12 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view) subframe->SetMenuBar(menu_bar); subframe->Centre(wxBOTH); - wxAcceleratorEntry accelEntries[3]; + wxAcceleratorEntry accelEntries[4]; accelEntries[0].Set (wxACCEL_CTRL, static_cast('E'), PLOTMENU_VIEW_SCALE_MINMAX); accelEntries[1].Set (wxACCEL_CTRL, static_cast('A'), PLOTMENU_VIEW_SCALE_AUTO); accelEntries[2].Set (wxACCEL_CTRL, static_cast('U'), PLOTMENU_VIEW_SCALE_FULL); - wxAcceleratorTable accelTable (3, accelEntries); + accelEntries[3].Set (wxACCEL_CTRL, static_cast('I'), PLOTMENU_FILE_PROPERTIES); + wxAcceleratorTable accelTable (4, accelEntries); subframe->SetAcceleratorTable (accelTable); return subframe; diff --git a/src/views.h b/src/views.h index 14a7e0c..9b5d44f 100644 --- a/src/views.h +++ b/src/views.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: views.h,v 1.45 2001/02/08 06:25:07 kevin Exp $ +** $Id: views.h,v 1.46 2001/02/22 11:05:38 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -35,6 +35,7 @@ #include "wx/wx.h" #include "docs.h" #include "imagefile.h" +#include "threadrecon.h" #if wxUSE_GLCANVAS #include "graph3dview.h" @@ -182,12 +183,12 @@ public: class ProjectionFileCanvas; class ProjectionFileView : public wxView { +private: DECLARE_DYNAMIC_CLASS(ProjectionFileView) - wxMemoryDC m_memoryDC; + wxMemoryDC m_memoryDC; wxBitmap m_bitmap; -private: ProjectionFileCanvas *CreateCanvas (wxFrame* parent); #if CTSIM_MDI wxDocMDIChildFrame* m_pFrame; @@ -199,7 +200,7 @@ private: ProjectionFileCanvas *m_pCanvas; wxMenu* m_pFileMenu; - + int m_iDefaultNX; int m_iDefaultNY; int m_iDefaultFilter; -- 2.34.1