r582: no message
[ctsim.git] / src / views.cpp
index 60eda6ab2633d86c0a31d26d655185bc1a3e4958..a4826e0292c0d7137c6ae94144788f9f64ab5335 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: views.cpp,v 1.112 2001/02/22 11:05:38 kevin Exp $
+**  $Id: views.cpp,v 1.118 2001/02/25 10:52:55 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
@@ -49,8 +49,6 @@
 #include "timer.h"
 #include "threadrecon.h"
 
-#define CTSIM_THREADS 1
-
 #if defined(MSVC) || HAVE_SSTREAM
 #include <sstream>
 #else
@@ -115,6 +113,7 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
 {
   if (! m_pView)
     return;
+
   
   wxClientDC dc(this);
   PrepareDC(dc);
@@ -385,7 +384,7 @@ ImageFileView::OnCompare (wxCommandEvent& event)
           return;
         }
         pDifferenceDoc->setImageFile (pDifferenceImage);
-
+        
         wxString s = GetFrame()->GetTitle() + ": ";
         pDifferenceImage->labelsCopy (rIF, s.c_str());
         s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
@@ -413,7 +412,7 @@ ImageFileView::OnInvertValues (wxCommandEvent& event)
   rIF.invertPixelValues (rIF);
   rIF.labelAdd ("Invert Pixel Values");
   if (theApp->getAskDeleteNewDocs())
-          GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -424,7 +423,7 @@ ImageFileView::OnSquare (wxCommandEvent& event)
   rIF.square (rIF);
   rIF.labelAdd ("Square Pixel Values");
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -435,7 +434,7 @@ ImageFileView::OnSquareRoot (wxCommandEvent& event)
   rIF.sqrt (rIF);
   rIF.labelAdd ("Square-root Pixel Values");
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -446,7 +445,7 @@ ImageFileView::OnLog (wxCommandEvent& event)
   rIF.log (rIF);
   rIF.labelAdd ("Logrithm base-e Pixel Values");
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -457,7 +456,7 @@ ImageFileView::OnExp (wxCommandEvent& event)
   rIF.exp (rIF);
   rIF.labelAdd ("Exponent base-e Pixel Values");
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -636,7 +635,7 @@ ImageFileView::OnFFT (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -649,7 +648,7 @@ ImageFileView::OnIFFT (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -662,7 +661,7 @@ ImageFileView::OnFFTRows (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -675,7 +674,7 @@ ImageFileView::OnIFFTRows (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -688,7 +687,7 @@ ImageFileView::OnFFTCols (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -701,7 +700,7 @@ ImageFileView::OnIFFTCols (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 #endif
@@ -716,7 +715,7 @@ ImageFileView::OnFourier (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -730,7 +729,7 @@ ImageFileView::OnInverseFourier (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -743,7 +742,7 @@ ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -756,7 +755,7 @@ ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)
   m_bMinSpecified = false;
   m_bMaxSpecified = false;
   if (theApp->getAskDeleteNewDocs())
-     GetDocument()->Modify (true);
+    GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
 }
 
@@ -770,7 +769,7 @@ ImageFileView::OnMagnitude (wxCommandEvent& event)
     m_bMinSpecified = false;
     m_bMaxSpecified = false;
     if (theApp->getAskDeleteNewDocs())
-       GetDocument()->Modify (true);
+      GetDocument()->Modify (true);
     GetDocument()->UpdateAllViews (this);
   }
 }
@@ -785,7 +784,7 @@ ImageFileView::OnPhase (wxCommandEvent& event)
     m_bMinSpecified = false;
     m_bMaxSpecified = false;
     if (theApp->getAskDeleteNewDocs())
-       GetDocument()->Modify (true);
+      GetDocument()->Modify (true);
     GetDocument()->UpdateAllViews (this);
   }
 }
@@ -936,7 +935,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
 #else
   wxAcceleratorTable accelTable (4, accelEntries);
 #endif
-
+  
   subframe->SetAcceleratorTable (accelTable);
   
   return subframe;
@@ -1003,6 +1002,10 @@ ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
     double scaleWidth = m_dMaxPixel - m_dMinPixel;
     
     unsigned char* imageData = new unsigned char [nx * ny * 3];
+    if (! imageData) {
+      sys_error (ERR_SEVERE, "Unable to allocate memory for Image display");
+      return;
+    }
     for (int ix = 0; ix < nx; ix++) {
       for (int iy = 0; iy < ny; iy++) {
         double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
@@ -1033,7 +1036,7 @@ ImageFileView::OnClose (bool deleteWindow)
   //GetDocumentManager()->ActivateView (this, false, true);
   if (! GetDocument() || ! GetDocument()->Close())
     return false;
-
+  
   Activate (false);
   if (m_pCanvas) {
     m_pCanvas->setView(NULL);
@@ -1125,7 +1128,7 @@ ImageFileView::OnScaleSize (wxCommandEvent& event)
     rIF.scaleImage (rScaledIF);
     *theApp->getLog() << os.str().c_str() << "\n";
     if (theApp->getAskDeleteNewDocs())
-       pScaledDoc->Modify (true);
+      pScaledDoc->Modify (true);
     pScaledDoc->UpdateAllViews (this);
     pScaledDoc->getView()->OnUpdate (this, NULL);
     pScaledDoc->getView()->getFrame()->Show(true);
@@ -1229,7 +1232,7 @@ ImageFileView::OnPlotRow (wxCommandEvent& event)
       delete pYMag;
     }
     if (theApp->getAskDeleteNewDocs())
-       pPlotDoc->Modify (true);
+      pPlotDoc->Modify (true);
     pPlotDoc->UpdateAllViews ();
     pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
@@ -1315,7 +1318,7 @@ ImageFileView::OnPlotCol (wxCommandEvent& event)
       delete pYMag;
     }
     if (theApp->getAskDeleteNewDocs())
-       pPlotDoc->Modify (true);
+      pPlotDoc->Modify (true);
     pPlotDoc->UpdateAllViews ();
     pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
@@ -1410,7 +1413,7 @@ ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
     delete [] pcIn;
     
     if (theApp->getAskDeleteNewDocs())
-       pPlotDoc->Modify (true);
+      pPlotDoc->Modify (true);
     pPlotDoc->UpdateAllViews ();
     pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
@@ -1511,7 +1514,7 @@ ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
     delete [] pcIn;
     
     if (theApp->getAskDeleteNewDocs())
-       pPlotDoc->Modify (true);
+      pPlotDoc->Modify (true);
     pPlotDoc->UpdateAllViews ();
     pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
@@ -1794,7 +1797,7 @@ PhantomCanvas::GetBestSize() const
 {
   if (! m_pView)
     return wxSize(0,0);
-
+  
   int xSize, ySize;
   theApp->getMainFrame()->GetClientSize (&xSize, &ySize);
   xSize = maxValue<int> (xSize, ySize);
@@ -1891,7 +1894,7 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
       const Phantom& rPhantom = GetDocument()->getPhantom();
       Projections* pProj = new Projections;
       Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, 
-                          m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultViewRatio, m_dDefaultScanRatio);
+        m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultViewRatio, m_dDefaultScanRatio);
       if (theScanner.fail()) {
         wxString msg = "Failed making scanner\n";
         msg += theScanner.failMessage().c_str();
@@ -1899,6 +1902,13 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
         wxMessageBox (msg, "Error");
         return;
       }
+      std::ostringstream os;
+      os << "Projections for " << rPhantom.name() << ": nDet=" << m_iDefaultNDet 
+        << ", nView=" << m_iDefaultNView << ", nSamples=" << m_iDefaultNSample 
+        << ", RotAngle=" << m_dDefaultRotation << ", FocalLengthRatio=" << m_dDefaultFocalLength 
+        << ", ViewRatio=" << m_dDefaultViewRatio << ", ScanRatio=" << m_dDefaultScanRatio 
+        << ", Geometry=" << sGeometry.c_str() << ", FanBeamAngle=" << 
+        convertRadiansToDegrees (theScanner.fanBeamAngle());
       pProj->initFromScanner (theScanner);
       m_dDefaultRotation /= TWOPI;  // convert back to fraction of a circle
       
@@ -1928,15 +1938,8 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
         }
       }
       
-      std::ostringstream os;
-      os << "Projections for " << rPhantom.name() << ": nDet=" << m_iDefaultNDet 
-        << ", nView=" << m_iDefaultNView << ", nSamples=" << m_iDefaultNSample 
-        << ", RotAngle=" << m_dDefaultRotation << ", FocalLengthRatio=" << m_dDefaultFocalLength 
-        << ", ViewRatio=" << m_dDefaultViewRatio << ", ScanRatio=" << m_dDefaultScanRatio 
-        << ", Geometry=" << sGeometry.c_str() << ", FanBeamAngle=" << 
-        convertRadiansToDegrees (theScanner.fanBeamAngle());
-      pProj->setCalcTime (timer.timerEnd());
       pProj->setRemark (os.str());
+      pProj->setCalcTime (timer.timerEnd());
       *theApp->getLog() << os.str().c_str() << "\n";
       
       ::wxYield();
@@ -1984,12 +1987,12 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
       m_dDefaultRasterViewRatio = 0;
     if (m_iDefaultRasterNX > 0 && m_iDefaultRasterNY > 0) {
       const Phantom& rPhantom = GetDocument()->getPhantom();
-
+      
       ImageFile* pImageFile = new ImageFile;
       
       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, 
@@ -1999,14 +2002,14 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
           return;
         }
       }
-
+      
       ImageFileDocument* pRasterDoc = theApp->newImageDoc();
       if (! pRasterDoc) {
         sys_error (ERR_SEVERE, "Unable to create image file");
         return;
       }
       pRasterDoc->setImageFile (pImageFile);
-
+      
       if (theApp->getAskDeleteNewDocs())
         pRasterDoc->Modify (true);
       pRasterDoc->UpdateAllViews (this);
@@ -2323,7 +2326,7 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
     m_iDefaultPolarNY = dialogPolar.getYSize();
     m_iDefaultPolarZeropad = dialogPolar.getZeropad();
     ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY);
-
+    
     m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
     if (! rProj.convertFFTPolar (*pIF, m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad)) {
       delete pIF;
@@ -2354,7 +2357,12 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
 void
 ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
 {
-#if CTSIM_THREADS
+  wxMessageBox ("Fourier Reconstruction is not yet supported", "Unimplemented function");
+}
+
+void
+ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
+{
   DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY, 
     m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, 
     m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, 
@@ -2378,20 +2386,20 @@ ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
     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) {
+        ImageFile* pImageFile = new ImageFile;
+        pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY);
         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);
-      
+          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();
@@ -2408,166 +2416,77 @@ ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
             ::wxUsleep(50);
           }
         }
+        pReconstructor->postProcessing();
         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;
+        ImageFileDocument* pReconDoc = theApp->newImageDoc();
+        if (! pReconDoc) {
+          sys_error (ERR_SEVERE, "Unable to create image file");
           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;
-          }
+        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);
         }
-      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
-ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
-{
-  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);
-      
-      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);
-      
-      Timer timerRecon;
-      if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
-        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;
+        *theApp->getLog() << os.str().c_str() << "\n";
+        pImageFile->labelAdd (rProj.getLabel());
+        pImageFile->labelAdd (os.str().c_str(), timerRecon.timerEnd());
+        
+      } else {
+        if (theApp->getUseBackgroundTasks() || theApp->getNumberCPU() > 1) {
+          ReconstructorSupervisorThread* pReconstructor = new ReconstructorSupervisorThread (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->Create() != wxTHREAD_NO_ERROR) {
+            sys_error (ERR_SEVERE, "Error creating reconstructor thread");
             delete pReconstructor;
-            delete pImageFile;
             return;
           }
-          ::wxYield();
-          ::wxYield();
-          while (pDlgReconstruct->isPaused()) {
-            ::wxYield();
-            ::wxUsleep(50);
+//          pReconstructor->SetPriority (60);
+          pReconstructor->Run();
+        } else {
+          ImageFile* pImageFile = new ImageFile;
+          pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY);
+          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 pDlgReconstruct;
-      } else {
-        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;
+          pReconstructor->postProcessing();
+          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());
         }
       }
-      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);
-      }
-      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();
-      *theApp->getLog() << os.str().c_str() << "\n";
-      pImageFile->labelAdd (rProj.getLabel());
-      pImageFile->labelAdd (os.str().c_str(), timerRecon.timerEnd());
     }
   }
 }
@@ -2634,10 +2553,8 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   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");
@@ -2727,6 +2644,10 @@ ProjectionFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint)
     }
     
     unsigned char* imageData = new unsigned char [nDet * nView * 3];
+    if (! imageData) {
+      sys_error (ERR_SEVERE, "Unable to allocate memory for image display");
+      return;
+    }
     double scale = (max - min) / 255;
     for (int iy2 = 0; iy2 < nView; iy2++) {
       const DetectorArray& detarray = rProj.getDetectorArray (iy2);
@@ -2777,7 +2698,7 @@ ProjectionFileView::OnClose (bool deleteWindow)
     if (GetDocument() && GetDocument()->getBadFileOpen())
       ::wxYield();  // wxWindows bug workaround
   }
-
+  
   return true;
 }
 
@@ -3101,8 +3022,8 @@ PlotFileView::OnClose (bool deleteWindow)
     m_pFrame = NULL;
     if (GetDocument() && GetDocument()->getBadFileOpen())
       ::wxYield();  // wxWindows bug workaround
- }
-
 }
+  
   return true;
 }
 
@@ -3169,7 +3090,7 @@ TextFileView::OnClose (bool deleteWindow)
     if (GetDocument() && GetDocument()->getBadFileOpen())
       ::wxYield();  // wxWindows bug workaround
   }
-
+  
   return TRUE;
 }
 
@@ -3187,7 +3108,7 @@ TextFileView::CreateChildFrame (wxDocument *doc, wxView *view)
 #endif
   theApp->setIconForFrame (subframe);
   
- m_pFileMenu = new wxMenu;
 m_pFileMenu = new wxMenu;
   
   m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
   m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
@@ -3221,7 +3142,7 @@ TextFileView::CreateChildFrame (wxDocument *doc, wxView *view)
   
   subframe->SetMenuBar(menu_bar);
   subframe->Centre(wxBOTH);
-    
+  
   return subframe;
 }