r571: no message
authorKevin M. Rosenberg <kevin@rosenberg.net>
Thu, 22 Feb 2001 11:05:38 +0000 (11:05 +0000)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Thu, 22 Feb 2001 11:05:38 +0000 (11:05 +0000)
18 files changed:
ChangeLog
doc/ctsim.prj
include/timer.h
libctsupport/interpolator.cpp
msvc/ctsim/ctsim.plg
src/ctsim.cpp
src/ctsim.h
src/dialogs.cpp
src/dlgprojections.cpp
src/dlgreconstruct.cpp
src/docs.cpp
src/docs.h
src/graph3dview.cpp
src/threadrecon.cpp [new file with mode: 0644]
src/threadrecon.h [new file with mode: 0644]
src/tips.cpp
src/views.cpp
src/views.h

index 67bcdc7dd1eb7c45db21573c738285ca654ad81a..00f074dd8992f26759a0ed58d719d28ed171620c 100644 (file)
--- 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
 
index 11ca2c4874f9069bdec80f12c87b3b879da3aad5..d9dd4aea4d69783ed9bb8114f20bf1b9a56cb900 100644 (file)
@@ -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
index e938ae91936411919f34ce030a9b47c93bec1577..226d258c85ca181fcaf1abe478be1efdb796de02 100644 (file)
@@ -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
 **  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
 
 
index e8abdfa0bfc259517b4978ec72818cb23f166b4d..bbc7f275866594063a67e74410a04ff92e913bc2 100644 (file)
@@ -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);
   }
 
index f240cfc7f8aebd2fe318790c3bd35592f3a934ef..6fdda36db4695c20ccb8cf68d1462ac799da14ca 100644 (file)
@@ -6,19 +6,23 @@
 --------------------Configuration: ctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
-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"
 <h3>Output Window</h3>
 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...
 
 
index 510e2487531ca0440831ec2e76aa5cf5f8044a80..1155aac3de857ab4996be27fbf8d55b310361158 100644 (file)
@@ -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
 #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::vector<Imag
 }
 
 
+void
+MainFrame::OnLogEvent (wxCommandEvent& event)
+{
+  *theApp->getLog() << event.GetString();
+}
+
 void
 MainFrame::OnHelpTips (wxCommandEvent& event)
 {
index a2c2afa8f0ffbdca845197b330dde5d9a38d3629..9768970a97d9c20b7008cf87ce993dec8e9fd947 100644 (file)
@@ -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
index 9915a34d8765959e2b8974f17889224fec72dfa2..8e253387987cc957d5461396fe1ff69a6b69dd5f 100644 (file)
@@ -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
 // #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
index e2d3a4402e4ce76dbfa61bcb16d8d3bea01c5182..76b0ae4e0a65693c7b677a6434f4e8aa39bc90d3 100644 (file)
@@ -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
 #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"
index 9f1b9506b6f9190446ece86e0c4588b77e071540..093586bedc8552631c9b46a9b42c773b8a1f1c94 100644 (file)
@@ -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
 #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"
index 93c5f1ea8d60954ccc54d007d644d842dd58e81b..460082a63ae8f3a14f1e30a1beccb1c322e21352 100644 (file)
@@ -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
 // #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)
 {
index e7b681570164faa8a6e8618921a4f206fa4c9c4e..88e362ec694cd4d9112c800d877a1d7c69aae4bc 100644 (file)
@@ -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<ThreadedReconstructor*> 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);
 };
 
 
index 7abec424082152bfdb0607f78b13c828a199e9ae..55fe7c1d9ece9bf2d8230685d624170ccadddabb 100644 (file)
@@ -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
 #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 (file)
index 0000000..aa9a7bb
--- /dev/null
@@ -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<int>(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<wxThread::ExitCode>(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<wxThread::ExitCode>(0);
+}
+
+void
+ReconstructionThread::OnExit ()
+{
+}
diff --git a/src/threadrecon.h b/src/threadrecon.h
new file mode 100644 (file)
index 0000000..53368fa
--- /dev/null
@@ -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 <vector>
+#include <wx/thread.h>
+#include <wx/progdlg.h>
+#include "timer.h"
+
+
+class Reconstructor;
+class ImageFile;
+class ProjectionFileDocument;
+class ReconstructionThread;
+class ProjectionFileView;
+
+class ThreadedReconstructor : public wxEvtHandler {
+private:
+  DECLARE_DYNAMIC_CLASS(ThreadedReconstructor)
+
+  std::vector<Reconstructor*> m_vecpReconstructor;
+  std::vector<ImageFile*> m_vecpChildImageFile;
+  std::vector<ReconstructionThread*> 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
index c263b48356aac5465dc3197086a2746a1e464485..dc425d6602731ae7a5e79cc806869b749b028df3 100644 (file)
@@ -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
 **  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
index c20009dbf38813fec99bc18711f64237e2527678..60eda6ab2633d86c0a31d26d655185bc1a3e4958 100644 (file)
@@ -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
 **  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 <sstream>
@@ -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<int>('A'), IFMENU_VIEW_SCALE_AUTO);
   accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('U'), IFMENU_VIEW_SCALE_FULL);
   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('E'), IFMENU_VIEW_SCALE_MINMAX);
+  accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('I'), IFMENU_FILE_PROPERTIES);
 #if wxUSE_GLCANVAS
-  accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
-  wxAcceleratorTable accelTable (4, accelEntries);
+  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('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<int>('J'), PHMMENU_PROCESS_PROJECTIONS);
   accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('R'), PHMMENU_PROCESS_RASTERIZE);
-  wxAcceleratorTable accelTable (2, accelEntries);
+  accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('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<int>('L'), PJMENU_CONVERT_POLAR);
-  accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_CONVERT_FFT_POLAR);
+  accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('M'), PJMENU_CONVERT_FFT_POLAR);
   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
   accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
-  wxAcceleratorTable accelTable (4, accelEntries);
+  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('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<int>('E'), PLOTMENU_VIEW_SCALE_MINMAX);
   accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('A'), PLOTMENU_VIEW_SCALE_AUTO);
   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('U'), PLOTMENU_VIEW_SCALE_FULL);
-  wxAcceleratorTable accelTable (3, accelEntries);
+  accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('I'), PLOTMENU_FILE_PROPERTIES);
+  wxAcceleratorTable accelTable (4, accelEntries);
   subframe->SetAcceleratorTable (accelTable);
   
   return subframe;
index 14a7e0c93913d80b271d0391408b722c42231c7d..9b5d44fccd18a08a296974db843840192f92315d 100644 (file)
@@ -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;