r636: Optimized Rebinning, Added Reconstruct with Rebinning option
[ctsim.git] / src / views.cpp
index b78442190c44e0f06aeade515d24e9dd9fd30369..8b40f35744b2fd2039288dfa165e1e3d2c4401a7 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
-**  $Id: views.cpp,v 1.124 2001/03/02 20:20:09 kevin Exp $
+**  $Id: views.cpp,v 1.137 2001/03/13 08:24:41 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
@@ -36,6 +36,7 @@
 
 #include "wx/image.h"
 #include "wx/progdlg.h"
+#include "wx/clipbrd.h"
 
 #include "ct.h"
 #include "ctsim.h"
@@ -204,6 +205,9 @@ IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
 BEGIN_EVENT_TABLE(ImageFileView, wxView)
 EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
+EVT_MENU(IFMENU_EDIT_COPY, ImageFileView::OnEditCopy)
+EVT_MENU(IFMENU_EDIT_CUT, ImageFileView::OnEditCut)
+EVT_MENU(IFMENU_EDIT_PASTE, ImageFileView::OnEditPaste)
 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
 EVT_MENU(IFMENU_VIEW_SCALE_FULL, ImageFileView::OnScaleFull)
@@ -289,6 +293,7 @@ ImageFileView::OnProperties (wxCommandEvent& event)
     wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
     dialogMsg.ShowModal();
   }
+  GetDocument()->Activate();
 }
 
 void 
@@ -307,9 +312,10 @@ ImageFileView::OnScaleAuto (wxCommandEvent& event)
       m_dMinPixel = dMin;
       m_dMaxPixel = dMax;
       m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
-      OnUpdate (this, NULL);
+      GetDocument()->UpdateAllViews (this);
     }
   }
+  GetDocument()->Activate();
 }
 
 void 
@@ -332,8 +338,9 @@ ImageFileView::OnScaleMinMax (wxCommandEvent& event)
     m_bMaxSpecified = true;
     m_dMinPixel = dialogMinMax.getMinimum();
     m_dMaxPixel = dialogMinMax.getMaximum();
-    OnUpdate (this, NULL);
+    GetDocument()->UpdateAllViews (this);
   }
+  GetDocument()->Activate();
 }
 
 void 
@@ -342,8 +349,9 @@ ImageFileView::OnScaleFull (wxCommandEvent& event)
   if (m_bMinSpecified || m_bMaxSpecified) {
     m_bMinSpecified = false;
     m_bMaxSpecified = false;
-    OnUpdate (this, NULL);
+    GetDocument()->UpdateAllViews (this);
   }
+  GetDocument()->Activate();
 }
 
 void
@@ -401,6 +409,7 @@ ImageFileView::OnCompare (wxCommandEvent& event)
         pDifferenceDoc->UpdateAllViews (this);
         pDifferenceDoc->getView()->OnUpdate (this, NULL);
         pDifferenceDoc->getView()->getFrame()->Show(true);
+        pDifferenceDoc->Activate();
       }
       wxMessageBox(os.str().c_str(), "Image Comparison");
     }
@@ -416,6 +425,7 @@ ImageFileView::OnInvertValues (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -427,6 +437,7 @@ ImageFileView::OnSquare (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -438,6 +449,7 @@ ImageFileView::OnSquareRoot (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -449,6 +461,7 @@ ImageFileView::OnLog (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -460,6 +473,7 @@ ImageFileView::OnExp (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -497,8 +511,8 @@ ImageFileView::OnAdd (wxCommandEvent& event)
       if (theApp->getAskDeleteNewDocs())
         pNewDoc->Modify (true);
       pNewDoc->UpdateAllViews (this);
-      pNewDoc->getView()->OnUpdate (this, NULL);
       pNewDoc->getView()->getFrame()->Show(true);
+      pNewDoc->Activate();
     }
   }
 }
@@ -538,8 +552,8 @@ ImageFileView::OnSubtract (wxCommandEvent& event)
       if (theApp->getAskDeleteNewDocs())
         pNewDoc->Modify (true);
       pNewDoc->UpdateAllViews (this);
-      pNewDoc->getView()->OnUpdate (this, NULL);
       pNewDoc->getView()->getFrame()->Show(true);
+      pNewDoc->Activate();
     }
   }
 }
@@ -579,8 +593,8 @@ ImageFileView::OnMultiply (wxCommandEvent& event)
       if (theApp->getAskDeleteNewDocs())
         pNewDoc->Modify (true);
       pNewDoc->UpdateAllViews (this);
-      pNewDoc->getView()->OnUpdate (this, NULL);
       pNewDoc->getView()->getFrame()->Show(true);
+      pNewDoc->Activate();
     }
   }
 }
@@ -620,8 +634,8 @@ ImageFileView::OnDivide (wxCommandEvent& event)
       if (theApp->getAskDeleteNewDocs())
         pNewDoc->Modify (true);
       pNewDoc->UpdateAllViews (this);
-      pNewDoc->getView()->OnUpdate (this, NULL);
       pNewDoc->getView()->getFrame()->Show(true);
+      pNewDoc->Activate();
     }
   }
 }
@@ -639,6 +653,7 @@ ImageFileView::OnFFT (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -652,6 +667,7 @@ ImageFileView::OnIFFT (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -665,6 +681,7 @@ ImageFileView::OnFFTRows (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -678,6 +695,7 @@ ImageFileView::OnIFFTRows (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -691,6 +709,7 @@ ImageFileView::OnFFTCols (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -704,6 +723,7 @@ ImageFileView::OnIFFTCols (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 #endif
 
@@ -719,6 +739,7 @@ ImageFileView::OnFourier (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -733,6 +754,7 @@ ImageFileView::OnInverseFourier (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -746,6 +768,7 @@ ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -759,6 +782,7 @@ ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     GetDocument()->Modify (true);
   GetDocument()->UpdateAllViews (this);
+  GetDocument()->Activate();
 }
 
 void
@@ -774,6 +798,7 @@ ImageFileView::OnMagnitude (wxCommandEvent& event)
       GetDocument()->Modify (true);
     GetDocument()->UpdateAllViews (this);
   }
+  GetDocument()->Activate();
 }
 
 void
@@ -789,6 +814,7 @@ ImageFileView::OnPhase (wxCommandEvent& event)
       GetDocument()->Modify (true);
     GetDocument()->UpdateAllViews (this);
   }
+  GetDocument()->Activate();
 }
 
 
@@ -841,7 +867,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
   m_pFileMenu->Append(wxID_PREVIEW, "Print Preview");
   m_pFileMenu->AppendSeparator();
-  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import\tCtrl-I...");
+  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import...\tCtrl-M");
 #ifdef CTSIM_MDI
   m_pFileMenu->AppendSeparator();
   m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");
@@ -850,6 +876,11 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
   GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
   
+  wxMenu* edit_menu = new wxMenu;
+  edit_menu->Append(IFMENU_EDIT_COPY, "Copy\tCtrl-C");
+  edit_menu->Append(IFMENU_EDIT_CUT, "Cut\tCtrl-X");
+  edit_menu->Append(IFMENU_EDIT_PASTE, "Paste\tCtrl-V");
+  
   wxMenu *view_menu = new wxMenu;
   view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale S&et...\tCtrl-E");
   view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...\tCtrl-A");
@@ -918,6 +949,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   wxMenuBar *menu_bar = new wxMenuBar;
   
   menu_bar->Append(m_pFileMenu, "&File");
+  menu_bar->Append(edit_menu, "&Edit");
   menu_bar->Append(view_menu, "&View");
   menu_bar->Append(image_menu, "&Image");
   menu_bar->Append(filter_menu, "Fi&lter");
@@ -928,16 +960,19 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   
   subframe->Centre(wxBOTH);
   
-  wxAcceleratorEntry accelEntries[5];
+  wxAcceleratorEntry accelEntries[8];
   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);
+  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('C'), IFMENU_EDIT_COPY);
+  accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('X'), IFMENU_EDIT_CUT);
+  accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('V'), IFMENU_EDIT_PASTE);
 #if wxUSE_GLCANVAS
-  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
-  wxAcceleratorTable accelTable (5, accelEntries);
+  accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
+  wxAcceleratorTable accelTable (8, accelEntries);
 #else
-  wxAcceleratorTable accelTable (4, accelEntries);
+  wxAcceleratorTable accelTable (7, accelEntries);
 #endif
   
   subframe->SetAcceleratorTable (accelTable);
@@ -1062,6 +1097,72 @@ ImageFileView::OnClose (bool deleteWindow)
   return true;
 }
 
+void
+ImageFileView::OnEditCopy (wxCommandEvent& event)
+{
+  wxBitmapDataObject *pBitmapObject = new wxBitmapDataObject;
+  
+  pBitmapObject->SetBitmap (m_bitmap);
+  
+  if (wxTheClipboard->Open()) {
+    wxTheClipboard->SetData (pBitmapObject);
+    wxTheClipboard->Close();
+  }
+}
+
+void
+ImageFileView::OnEditCut (wxCommandEvent& event)
+{
+  OnEditCopy (event);
+  ImageFile& rIF = GetDocument()->getImageFile();
+  int nx = rIF.nx();
+  int ny = rIF.ny();
+  ImageFile* pIF = new ImageFile (nx, ny);
+  pIF->arrayDataClear();
+  GetDocument()->setImageFile (pIF); // deletes old IF
+  OnUpdate(this, NULL);
+  GetDocument()->UpdateAllViews();
+  if (theApp->getAskDeleteNewDocs())
+    GetDocument()->Modify (true);
+}
+
+void
+ImageFileView::OnEditPaste (wxCommandEvent& event)
+{
+  ImageFile& rIF = GetDocument()->getImageFile();
+  
+  if (wxTheClipboard->Open()) {
+    wxBitmap bitmap;
+    if (wxTheClipboard->IsSupported (wxDF_BITMAP)) {
+      wxBitmapDataObject bitmapObject;
+      wxTheClipboard->GetData (bitmapObject);
+      bitmap = bitmapObject.GetBitmap ();
+    }
+    wxTheClipboard->Close();
+    
+    int nx = rIF.nx();
+    int ny = rIF.ny();
+    if (bitmap.Ok() == true && bitmap.GetWidth() == nx && bitmap.GetHeight() == ny) {
+      wxImage image (bitmap);
+      unsigned char* pixels = image.GetData();
+      ImageFileArray v = rIF.getArray();
+      for (int ix = 0; ix < rIF.nx(); ix++) {
+        for (int iy = 0; iy < rIF.ny(); iy++) {
+          unsigned int iBase = 3 * (iy * nx + ix);
+          double dR = pixels[iBase] / 255.;
+          double dG = pixels[iBase+1] / 255.;
+          double dB = pixels[iBase+2] / 255.;
+          v[ix][ny - 1 - iy] = ImageFile::colorToGrayscale (dR, dG, dB);
+        }
+      }
+      OnUpdate(this, NULL);
+      GetDocument()->UpdateAllViews();
+      if (theApp->getAskDeleteNewDocs())
+        GetDocument()->Modify(true);
+    }
+  }
+}
+
 void
 ImageFileView::OnExport (wxCommandEvent& event)
 {
@@ -1095,6 +1196,12 @@ ImageFileView::OnExport (wxCommandEvent& event)
         strExt = ".png";
         strWildcard = "PNG Files (*.png)|*.png";
       }
+#endif
+#ifdef HAVE_CTN_DICOM
+      else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_DICOM) {
+        strExt = "";
+        strWildcard = "DICOM Files (*.*)|*.*";
+      }
 #endif
       else {
         strExt = "";
@@ -1138,8 +1245,8 @@ ImageFileView::OnScaleSize (wxCommandEvent& event)
     if (theApp->getAskDeleteNewDocs())
       pScaledDoc->Modify (true);
     pScaledDoc->UpdateAllViews (this);
-    pScaledDoc->getView()->OnUpdate (this, NULL);
     pScaledDoc->getView()->getFrame()->Show(true);
+    pScaledDoc->Activate();
   }
 }
 
@@ -1241,9 +1348,9 @@ ImageFileView::OnPlotRow (wxCommandEvent& event)
     }
     if (theApp->getAskDeleteNewDocs())
       pPlotDoc->Modify (true);
-    pPlotDoc->UpdateAllViews ();
-    pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
+    pPlotDoc->UpdateAllViews ();
+    pPlotDoc->Activate();
   }
 }
 
@@ -1327,9 +1434,9 @@ ImageFileView::OnPlotCol (wxCommandEvent& event)
     }
     if (theApp->getAskDeleteNewDocs())
       pPlotDoc->Modify (true);
-    pPlotDoc->UpdateAllViews ();
-    pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
+    pPlotDoc->UpdateAllViews ();
+    pPlotDoc->Activate();
   }
 }
 
@@ -1408,7 +1515,7 @@ ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
       rPlotFile.addColumn (1, pYReal);
       rPlotFile.addColumn (2, pYImag);
       rPlotFile.addColumn (3, pYMag);
-      for (int iL = 0; iL < rIF.nLabels(); iL++)
+      for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
         rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
       os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
       *theApp->getLog() << os.str().c_str() << "\n";
@@ -1422,9 +1529,9 @@ ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
     
     if (theApp->getAskDeleteNewDocs())
       pPlotDoc->Modify (true);
-    pPlotDoc->UpdateAllViews ();
-    pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
+    pPlotDoc->UpdateAllViews ();
+    pPlotDoc->Activate();
   }
 }
 
@@ -1508,7 +1615,7 @@ ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
       rPlotFile.addColumn (1, pYReal);
       rPlotFile.addColumn (2, pYImag);
       rPlotFile.addColumn (3, pYMag);
-      for (int iL = 0; iL < rIF.nLabels(); iL++)
+      for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
         rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
       os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
       *theApp->getLog() << os.str().c_str() << "\n";
@@ -1523,9 +1630,9 @@ ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
     
     if (theApp->getAskDeleteNewDocs())
       pPlotDoc->Modify (true);
-    pPlotDoc->UpdateAllViews ();
-    pPlotDoc->getView()->OnUpdate (this, NULL);
     pPlotDoc->getView()->getFrame()->Show(true);
+    pPlotDoc->UpdateAllViews ();
+    pPlotDoc->Activate();
   }
 }
 #endif
@@ -1614,9 +1721,9 @@ ImageFileView::OnCompareCol (wxCommandEvent& event)
       delete pY2;
       if (theApp->getAskDeleteNewDocs())
         pPlotDoc->Modify (true);
-      pPlotDoc->UpdateAllViews ();
-      pPlotDoc->getView()->OnUpdate (this, NULL);
       pPlotDoc->getView()->getFrame()->Show(true);
+      pPlotDoc->UpdateAllViews ();
+      pPlotDoc->Activate();
     }
   }
 }
@@ -1706,9 +1813,9 @@ ImageFileView::OnCompareRow (wxCommandEvent& event)
       delete pY2;
       if (theApp->getAskDeleteNewDocs())
         pPlotDoc->Modify (true);
-      pPlotDoc->UpdateAllViews ();
-      pPlotDoc->getView()->OnUpdate (this, NULL);
       pPlotDoc->getView()->getFrame()->Show(true);
+      pPlotDoc->UpdateAllViews ();
+      pPlotDoc->Activate();
     }
   }
 }
@@ -1773,9 +1880,9 @@ ImageFileView::OnPlotHistogram (wxCommandEvent& event)
       delete pY;
       if (theApp->getAskDeleteNewDocs())
         pPlotDoc->Modify (true);
-      pPlotDoc->UpdateAllViews ();
-      pPlotDoc->getView()->OnUpdate (this, NULL);
       pPlotDoc->getView()->getFrame()->Show(true);
+      pPlotDoc->UpdateAllViews ();
+      pPlotDoc->Activate();
   }
 }
 
@@ -1877,6 +1984,7 @@ PhantomFileView::OnProperties (wxCommandEvent& event)
 #endif
   *theApp->getLog() << ">>>>\n" << os.str().c_str() << "<<<<\n";
   wxMessageBox (os.str().c_str(), "Phantom Properties");
+  GetDocument()->Activate();
 }
 
 
@@ -1948,7 +2056,8 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
       }
     }
   } else {
-    if (theApp->getUseBackgroundTasks() || theApp->getNumberCPU() > 1) {
+#if HAVE_WXTHREADS
+    if (theApp->getUseBackgroundTasks()) {
       ProjectorSupervisorThread* pProjector = new ProjectorSupervisorThread (this, m_iDefaultNDet,
         m_iDefaultNView, sGeometry.c_str(), m_iDefaultNSample, dRotationRadians,
         m_dDefaultFocalLength, m_dDefaultCenterDetectorLength, m_dDefaultViewRatio, m_dDefaultScanRatio, os.str().c_str());
@@ -1960,7 +2069,9 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
       pProjector->SetPriority(60);
       pProjector->Run();
       return;
-    } else {
+    } else     
+#endif // HAVE_WXTHREADS
+    {
       pProj = new Projections;
       pProj->initFromScanner (theScanner);
       wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), pProj->nView() + 1, getFrameForChild(), wxPD_CAN_ABORT );
@@ -1999,6 +2110,7 @@ PhantomFileView::OnProjections (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     pProjectionDoc-> Modify(true);
   pProjectionDoc->UpdateAllViews (this);
+  pProjectionDoc->Activate();
 }
 
 
@@ -2027,8 +2139,9 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
   os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << m_iDefaultRasterNX << ", YSize=" 
     << m_iDefaultRasterNY << ", ViewRatio=" << m_dDefaultRasterViewRatio << ", nSamples=" 
     << m_iDefaultRasterNSamples;;
-
-  if (theApp->getUseBackgroundTasks() || theApp->getNumberCPU() > 1) {
+  
+#if HAVE_WXTHREADS
+  if (theApp->getUseBackgroundTasks()) {
     RasterizerSupervisorThread* pThread = new RasterizerSupervisorThread (this, m_iDefaultRasterNX, m_iDefaultRasterNY,
       m_iDefaultRasterNSamples, m_dDefaultRasterViewRatio, os.str().c_str());
     if (pThread->Create() != wxTHREAD_NO_ERROR) {
@@ -2037,7 +2150,9 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
     }
     pThread->SetPriority (60);
     pThread->Run();
-  } else {
+  } else 
+#endif
+  {
     ImageFile* pImageFile = new ImageFile (m_iDefaultRasterNX, m_iDefaultRasterNY);
     wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), 
       pImageFile->nx() + 1, getFrameForChild(), wxPD_CAN_ABORT );
@@ -2049,7 +2164,7 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
         return;
       }
     }
-  
+    
     ImageFileDocument* pRasterDoc = theApp->newImageDoc();
     if (! pRasterDoc) {
       sys_error (ERR_SEVERE, "Unable to create image file");
@@ -2067,6 +2182,7 @@ PhantomFileView::OnRasterize (wxCommandEvent& event)
       rasterView->getFrame()->SetFocus();
       rasterView->OnUpdate (rasterView, NULL);
     }
+    pRasterDoc->Activate();
   }
 }
 
@@ -2113,7 +2229,7 @@ PhantomFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
   m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
   m_pFileMenu->AppendSeparator();
-  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import\tCtrl-I...");
+  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import...\tCtrl-M");
 #ifdef CTSIM_MDI
   m_pFileMenu->AppendSeparator();
   m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");
@@ -2262,11 +2378,16 @@ 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_FBP_REBIN, ProjectionFileView::OnReconstructFBPRebin)
 EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier)
 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
+EVT_MENU(PJMENU_CONVERT_PARALLEL, ProjectionFileView::OnConvertParallel)
+EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling)
+EVT_MENU(PJMENU_ARTIFACT_REDUCTION, ProjectionFileView::OnArtifactReduction)
 END_EVENT_TABLE()
 
+
 ProjectionFileView::ProjectionFileView() 
 : wxView(), m_pFrame(0), m_pCanvas(0), m_pFileMenu(0)
 {
@@ -2314,6 +2435,7 @@ ProjectionFileView::OnProperties (wxCommandEvent& event)
   *theApp->getLog() << ">>>>\n" << os.str().c_str() << "<<<<\n";
   wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Projection File Properties", wxOK | wxICON_INFORMATION);
   dialogMsg.ShowModal();
+  GetDocument()->Activate();
 }
 
 
@@ -2324,17 +2446,20 @@ ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
   DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
     m_iDefaultPolarInterpolation, -1);
   if (dialogPolar.ShowModal() == wxID_OK) {
+    wxProgressDialog dlgProgress (wxString("Convert Polar"), wxString("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
     wxString strInterpolation (dialogPolar.getInterpolationName());
     m_iDefaultPolarNX = dialogPolar.getXSize();
     m_iDefaultPolarNY = dialogPolar.getYSize();
     ImageFileDocument* pPolarDoc = theApp->newImageDoc();
     ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY);
     m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
+    
     if (! rProj.convertPolar (*pIF, m_iDefaultPolarInterpolation)) {
       delete pIF;
       *theApp->getLog() << "Error converting to Polar\n";
       return;
     }
+    
     pPolarDoc = theApp->newImageDoc ();
     if (! pPolarDoc) {
       sys_error (ERR_SEVERE, "Unable to create image file");
@@ -2350,9 +2475,9 @@ ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
     pIF->labelAdd (os.str().c_str());
     if (theApp->getAskDeleteNewDocs())
       pPolarDoc->Modify (true);
-    pPolarDoc->UpdateAllViews ();
-    pPolarDoc->getView()->OnUpdate (this, NULL);
     pPolarDoc->getView()->getFrame()->Show(true);
+    pPolarDoc->UpdateAllViews ();
+    pPolarDoc->Activate();
   }
 }
 
@@ -2363,6 +2488,7 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
   DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert to FFT Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
     m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad);
   if (dialogPolar.ShowModal() == wxID_OK) {
+    wxProgressDialog dlgProgress (wxString("Convert FFT Polar"), wxString("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
     wxString strInterpolation (dialogPolar.getInterpolationName());
     m_iDefaultPolarNX = dialogPolar.getXSize();
     m_iDefaultPolarNY = dialogPolar.getYSize();
@@ -2390,10 +2516,82 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
     pIF->labelAdd (os.str().c_str());
     if (theApp->getAskDeleteNewDocs())
       pPolarDoc->Modify (true);
-    pPolarDoc->UpdateAllViews ();
-    pPolarDoc->getView()->OnUpdate (this, NULL);
     pPolarDoc->getView()->getFrame()->Show(true);
+    pPolarDoc->UpdateAllViews ();
+    pPolarDoc->Activate();
+  }
+}
+
+void
+ProjectionFileView::OnPlotTThetaSampling (wxCommandEvent& event)
+{
+  DialogGetThetaRange dlgTheta (this->getFrame(), ParallelRaysums::THETA_RANGE_UNCONSTRAINED);
+  if (dlgTheta.ShowModal() != wxID_OK)
+    return;
+  
+  int iThetaRange = dlgTheta.getThetaRange();
+  
+  Projections& rProj = GetDocument()->getProjections();
+  ParallelRaysums parallel (&rProj, iThetaRange);
+  PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
+  PlotFile& rPlot = pPlotDoc->getPlotFile();
+  ParallelRaysums::CoordinateContainer& coordContainer = parallel.getCoordinates();
+  double* pdT = new double [parallel.getNumCoordinates()];
+  double* pdTheta = new double [parallel.getNumCoordinates()];
+  
+  for (int i = 0; i < parallel.getNumCoordinates(); i++) {
+    pdT[i] = coordContainer[i]->m_dT;
+    pdTheta[i] = coordContainer[i]->m_dTheta;
+  }
+  rPlot.setCurveSize (2, parallel.getNumCoordinates(), true);
+  rPlot.addEzsetCommand ("title T-Theta Sampling");
+  rPlot.addEzsetCommand ("xlabel T");
+  rPlot.addEzsetCommand ("ylabel Theta");
+  rPlot.addEzsetCommand ("curve 1");
+  if (rProj.nDet() < 50 && rProj.nView() < 50)
+    rPlot.addEzsetCommand ("symbol 1"); // x symbol
+  else
+    rPlot.addEzsetCommand ("symbol 6"); // point symbol
+  rPlot.addEzsetCommand ("noline");
+  rPlot.addColumn (0, pdT);
+  rPlot.addColumn (1, pdTheta);
+  delete pdT;
+  delete pdTheta;
+  if (theApp->getAskDeleteNewDocs())
+    pPlotDoc->Modify (true);
+  pPlotDoc->getView()->getFrame()->Show(true);
+  pPlotDoc->UpdateAllViews ();
+  pPlotDoc->Activate();
+}
+
+void
+ProjectionFileView::OnConvertParallel (wxCommandEvent& event)
+{
+  Projections& rProj = GetDocument()->getProjections();
+  if (rProj.geometry() == Scanner::GEOMETRY_PARALLEL) {
+    wxMessageBox ("Projections are already parallel", "Error");
+    return;
+  }
+  wxProgressDialog dlgProgress (wxString("Convert to Parallel"), wxString("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
+  Projections* pProjNew = rProj.interpolateToParallel();
+  ProjectionFileDocument* pProjDocNew = theApp->newProjectionDoc();
+  pProjDocNew->setProjections (pProjNew);  
+  
+  if (ProjectionFileView* projView = pProjDocNew->getView()) {
+    projView->OnUpdate (projView, NULL);
+    if (projView->getCanvas())
+      projView->getCanvas()->SetClientSize (pProjNew->nDet(), pProjNew->nView());
+    if (wxFrame* pFrame = projView->getFrame()) {
+      pFrame->Show(true);
+      pFrame->SetFocus();
+      pFrame->Raise();
+    }
+    GetDocumentManager()->ActivateView (projView, true, false);
   }
+  if (theApp->getAskDeleteNewDocs())
+    pProjDocNew-> Modify(true);
+  pProjDocNew->UpdateAllViews (this);
+  pProjDocNew->Activate();
 }
 
 void
@@ -2402,13 +2600,33 @@ ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
   wxMessageBox ("Fourier Reconstruction is not yet supported", "Unimplemented function");
 }
 
+void
+ProjectionFileView::OnReconstructFBPRebin (wxCommandEvent& event)
+{
+  Projections& rProj = GetDocument()->getProjections();
+  doReconstructFBP (rProj, true);
+}
+
 void
 ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
 {
+  Projections& rProj = GetDocument()->getProjections();
+  doReconstructFBP (rProj, false);
+}
+
+void
+ProjectionFileView::doReconstructFBP (const Projections& rProj, bool bRebinToParallel)
+{
+  ReconstructionROI defaultROI;
+  defaultROI.m_dXMin = -rProj.phmLen() / 2;
+  defaultROI.m_dXMax = defaultROI.m_dXMin + rProj.phmLen();
+  defaultROI.m_dYMin = -rProj.phmLen() / 2;
+  defaultROI.m_dYMax = defaultROI.m_dYMin + rProj.phmLen();
+  
   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);
+    m_iDefaultTrace,  &defaultROI);
   
   int retVal = dialogReconstruction.ShowModal();
   if (retVal != wxID_OK)
@@ -2430,21 +2648,24 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
   wxString optBackprojectName = dialogReconstruction.getBackprojectName();
   m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str());
   m_iDefaultTrace = dialogReconstruction.getTrace();
+  dialogReconstruction.getROI (&defaultROI);
   
   if (m_iDefaultNX <= 0 && m_iDefaultNY <= 0) 
     return;
   
-  const Projections& rProj = GetDocument()->getProjections();
   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();
-  
+  if (bRebinToParallel)
+    os << "; Interpolate to Parallel";
+
   Timer timerRecon;
   ImageFile* pImageFile = NULL;
   if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
     pImageFile = new ImageFile (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);
+      optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace, 
+      &defaultROI, bRebinToParallel);
     
     ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstructor, rProj, *pImageFile, m_iDefaultTrace, getFrameForChild());
     for (int iView = 0; iView < rProj.nView(); iView++) {
@@ -2465,11 +2686,12 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
     delete pDlgReconstruct;
     delete pReconstructor;
   } 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 HAVE_WXTHREADS
+    if (theApp->getUseBackgroundTasks()) {
+      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(), &defaultROI, bRebinToParallel);
       if (pReconstructor->Create() != wxTHREAD_NO_ERROR) {
         sys_error (ERR_SEVERE, "Error creating reconstructor thread");
         delete pReconstructor;
@@ -2478,13 +2700,16 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
       pReconstructor->SetPriority (60);
       pReconstructor->Run();
       return;
-    } else {
+    } else 
+#endif
+    {
       pImageFile = new ImageFile (m_iDefaultNX, m_iDefaultNY);
+      wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT );
       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);
+        optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace, 
+        &defaultROI, bRebinToParallel);
       
-      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)) {
@@ -2505,6 +2730,7 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
   if (theApp->getAskDeleteNewDocs())
     pReconDoc->Modify (true);
   pReconDoc->UpdateAllViews (this);
+  pReconDoc->Activate();
   if (ImageFileView* rasterView = pReconDoc->getView()) {
     rasterView->OnUpdate (rasterView, NULL);
     rasterView->getFrame()->SetFocus();
@@ -2516,6 +2742,12 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
 }
 
 
+void
+ProjectionFileView::OnArtifactReduction (wxCommandEvent& event)
+{
+}
+
+
 ProjectionFileCanvas* 
 ProjectionFileView::CreateCanvas (wxFrame *parent)
 {
@@ -2563,7 +2795,7 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
   m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
   m_pFileMenu->AppendSeparator();
-  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import\tCtrl-I...");
+  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import...\tCtrl-M");
 #ifdef CTSIM_MDI
   m_pFileMenu->AppendSeparator();
   m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");
@@ -2575,9 +2807,18 @@ 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-M");
+  convert_menu->AppendSeparator();
+  convert_menu->Append (PJMENU_CONVERT_PARALLEL, "&Interpolate to Parallel");
+  
+  wxMenu* filter_menu = new wxMenu;
+  filter_menu->Append (PJMENU_ARTIFACT_REDUCTION, "&Artifact Reduction");
+  
+  wxMenu* analyze_menu = new wxMenu;
+  analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "&Plot T-Theta Sampling\tCtrl-T");
   
   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_FBP_REBIN, "Filtered &Backprojection (Rebin to Parallel)...\tCtrl-B", "Reconstruct image using filtered backprojection");
   reconstruct_menu->Append (PJMENU_RECONSTRUCT_FOURIER, "&Fourier...\tCtrl-E", "Reconstruct image using inverse Fourier");
   reconstruct_menu->Enable (PJMENU_RECONSTRUCT_FOURIER, false);
   
@@ -2591,19 +2832,23 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   
   menu_bar->Append (m_pFileMenu, "&File");
   menu_bar->Append (convert_menu, "&Convert");
+  menu_bar->Append (filter_menu, "Fi&lter");
+  menu_bar->Append (analyze_menu, "&Analyze");
   menu_bar->Append (reconstruct_menu, "&Reconstruct");
   menu_bar->Append (help_menu, "&Help");
   
   subframe->SetMenuBar(menu_bar);  
   subframe->Centre(wxBOTH);
   
-  wxAcceleratorEntry accelEntries[5];
+  wxAcceleratorEntry accelEntries[7];
   accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_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);
-  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
-  wxAcceleratorTable accelTable (5, accelEntries);
+  accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('B'), PJMENU_RECONSTRUCT_FBP_REBIN);
+  accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
+  accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
+  accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_PLOT_TTHETA_SAMPLING);
+  wxAcceleratorTable accelTable (7, accelEntries);
   subframe->SetAcceleratorTable (accelTable);
   
   return subframe;
@@ -2784,6 +3029,7 @@ PlotFileView::OnProperties (wxCommandEvent& event)
   *theApp->getLog() << ">>>>\n" << os.str().c_str() << "<<<<<\n";
   wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
   dialogMsg.ShowModal();
+  GetDocument()->Activate();
 }
 
 
@@ -2806,6 +3052,7 @@ PlotFileView::OnScaleAuto (wxCommandEvent& event)
       OnUpdate (this, NULL);
     }
   }
+  GetDocument()->Activate();
 }
 
 void 
@@ -2836,6 +3083,7 @@ PlotFileView::OnScaleMinMax (wxCommandEvent& event)
     m_dMaxPixel = dialogMinMax.getMaximum();
     OnUpdate (this, NULL);
   }
+  GetDocument()->Activate();
 }
 
 void 
@@ -2846,6 +3094,7 @@ PlotFileView::OnScaleFull (wxCommandEvent& event)
     m_bMaxSpecified = false;
     OnUpdate (this, NULL);
   }
+  GetDocument()->Activate();
 }
 
 
@@ -2895,7 +3144,7 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
   m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
   m_pFileMenu->AppendSeparator();
-  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import\tCtrl-I...");
+  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import...\tCtrl-M");
 #ifdef CTSIM_MDI
   m_pFileMenu->AppendSeparator();
   m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");
@@ -2987,6 +3236,7 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
   const PlotFile& rPlotFile = GetDocument()->getPlotFile();
   const int iNColumns = rPlotFile.getNumColumns();
   const int iNRecords = rPlotFile.getNumRecords();
+  const bool bScatterPlot = rPlotFile.getIsScatterPlot();
   
   if (iNColumns > 0 && iNRecords > 0) {
     if (m_pEZPlot)
@@ -3011,16 +3261,21 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
     m_pEZPlot->ezset("box");
     m_pEZPlot->ezset("grid");
     
-    double* pdXaxis = new double [iNRecords];
-    rPlotFile.getColumn (0, pdXaxis);
-    
+    double* pdX = new double [iNRecords];
     double* pdY = new double [iNRecords];
-    for (int iCol = 1; iCol < iNColumns; iCol++) {
-      rPlotFile.getColumn (iCol, pdY);
-      m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords);
+    if (! bScatterPlot) {
+      rPlotFile.getColumn (0, pdX);
+      
+      for (int iCol = 1; iCol < iNColumns; iCol++) {
+        rPlotFile.getColumn (iCol, pdY);
+        m_pEZPlot->addCurve (pdX, pdY, iNRecords);
+      }
+    } else {
+      rPlotFile.getColumn (0, pdX);
+      rPlotFile.getColumn (1, pdY);
+      m_pEZPlot->addCurve (pdX, pdY, iNRecords);
     }
-    
-    delete pdXaxis;
+    delete pdX;
     delete pdY;
   }
   
@@ -3150,7 +3405,7 @@ TextFileView::CreateChildFrame (wxDocument *doc, wxView *view)
   m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
   m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
   m_pFileMenu->AppendSeparator();
-  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import\tCtrl-I...");
+  m_pFileMenu->Append(MAINMENU_IMPORT, "&Import...\tCtrl-M");
 #ifdef CTSIM_MDI
   m_pFileMenu->AppendSeparator();
   m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");