1 /*****************************************************************************
5 ** Purpose: View & Canvas routines for CTSim program
6 ** Programmer: Kevin Rosenberg
7 ** Date Started: July 2000
9 ** This is part of the CTSim program
10 ** Copyright (C) 1983-2000 Kevin Rosenberg
12 ** $Id: views.cpp,v 1.43 2001/01/01 10:14:34 kevin Exp $
14 ** This program is free software; you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License (version 2) as
16 ** published by the Free Software Foundation.
18 ** This program is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ** GNU General Public License for more details.
23 ** You should have received a copy of the GNU General Public License
24 ** along with this program; if not, write to the Free Software
25 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ******************************************************************************/
28 // For compilers that support precompilation, includes "wx/wx.h".
29 #include "wx/wxprec.h"
39 #if !wxUSE_DOC_VIEW_ARCHITECTURE
40 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
44 #include "wx/progdlg.h"
51 #include "dlgprojections.h"
52 #include "dlgreconstruct.h"
53 #include "backprojectors.h"
54 #include "reconstruct.h"
57 #if defined(MSVC) || HAVE_SSTREAM
\r
60 #include <sstream_subst>
\r
66 BEGIN_EVENT_TABLE(ImageFileCanvas, wxScrolledWindow)
67 EVT_MOUSE_EVENTS(ImageFileCanvas::OnMouseEvent)
71 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
72 : wxScrolledWindow(frame, -1, pos, size, style)
80 ImageFileCanvas::OnDraw(wxDC& dc)
83 m_pView->OnDraw(& dc);
87 ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y)
\r
89 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
\r
93 int yPt = ny - y - 1;
\r
94 dc.SetLogicalFunction (wxINVERT);
\r
95 dc.SetPen (*wxGREEN_PEN);
\r
96 dc.DrawLine (0, yPt, nx, yPt);
\r
97 dc.DrawLine (x, 0, x, ny);
\r
98 dc.SetLogicalFunction (wxCOPY);
\r
102 ImageFileCanvas::GetCurrentCursor (int& x, int& y)
\r
107 if (m_xCursor >= 0 && m_yCursor >= 0)
\r
114 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
122 wxPoint pt(event.GetLogicalPosition(dc));
124 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
\r
125 ImageFileArrayConst v = rIF.getArray();
\r
128 const int yPt = ny - 1 - pt.y;
\r
129 if (event.RightIsDown()) {
\r
130 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
\r
131 std::ostringstream os;
\r
132 os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt];
\r
133 if (rIF.isComplex()) {
\r
134 double dImag = rIF.getImaginaryArray()[pt.x][yPt];
\r
136 os << " - " << -dImag;
\r
138 os << " + " << dImag;
\r
142 *theApp->getLog() << os.str().c_str();
\r
144 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
\r
146 else if (event.LeftIsDown() || event.LeftUp() || event.RightUp()) {
\r
147 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
\r
148 if (m_xCursor >= 0 && m_yCursor >= 0) {
\r
149 DrawRubberBandCursor (dc, m_xCursor, m_yCursor);
\r
151 DrawRubberBandCursor (dc, pt.x, yPt);
\r
155 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
\r
157 if (event.LeftUp()) {
\r
158 std::ostringstream os;
\r
159 os << "Selected column " << pt.x << " , row " << yPt << "\n";
\r
160 *theApp->getLog() << os.str().c_str();
\r
166 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
168 BEGIN_EVENT_TABLE(ImageFileView, wxView)
169 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
170 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
171 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
\r
172 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)
\r
173 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)
\r
174 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)
\r
175 EVT_MENU(IFMENU_PROCESS_INVERTVALUES, ImageFileView::OnInvertValues)
\r
176 EVT_MENU(IFMENU_PROCESS_SQUARE, ImageFileView::OnSquare)
\r
177 EVT_MENU(IFMENU_PROCESS_SQRT, ImageFileView::OnSquareRoot)
\r
178 EVT_MENU(IFMENU_PROCESS_LOG, ImageFileView::OnLog)
\r
179 EVT_MENU(IFMENU_PROCESS_EXP, ImageFileView::OnExp)
\r
180 EVT_MENU(IFMENU_PROCESS_FOURIER, ImageFileView::OnFourier)
\r
181 EVT_MENU(IFMENU_PROCESS_INVERSE_FOURIER, ImageFileView::OnInverseFourier)
\r
183 EVT_MENU(IFMENU_PROCESS_FFT, ImageFileView::OnFFT)
\r
184 EVT_MENU(IFMENU_PROCESS_IFFT, ImageFileView::OnIFFT)
\r
186 EVT_MENU(IFMENU_PROCESS_MAGNITUDE, ImageFileView::OnMagnitude)
\r
187 EVT_MENU(IFMENU_PROCESS_PHASE, ImageFileView::OnPhase)
\r
188 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)
\r
189 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)
\r
192 ImageFileView::ImageFileView(void)
193 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
197 ImageFileView::~ImageFileView(void)
202 ImageFileView::OnProperties (wxCommandEvent& event)
204 const ImageFile& rIF = GetDocument()->getImageFile();
205 if (rIF.nx() == 0 || rIF.ny() == 0)
206 *theApp->getLog() << "Properties: empty imagefile\n";
208 const std::string& rFilename = rIF.getFilename();
209 std::ostringstream os;
210 double min, max, mean, mode, median, stddev;
\r
211 rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);
\r
212 os << "Filename: " << rFilename << "\n";
\r
213 os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";
\r
214 os << "Data type: ";
\r
215 if (rIF.isComplex())
\r
219 os << "\nMinimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
220 if (rIF.isComplex()) {
\r
221 rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);
\r
222 os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";
\r
224 *theApp->getLog() << os.str().c_str();
225 wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
226 dialogMsg.ShowModal();
231 ImageFileView::OnScaleAuto (wxCommandEvent& event)
233 const ImageFile& rIF = GetDocument()->getImageFile();
234 double min, max, mean, mode, median, stddev;
\r
235 rIF.statistics(min, max, mean, mode, median, stddev);
\r
236 DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor);
237 int iRetVal = dialogAutoScale.ShowModal();
238 if (iRetVal == wxID_OK) {
239 m_bMinSpecified = true;
240 m_bMaxSpecified = true;
242 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
245 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
246 OnUpdate (this, NULL);
\r
252 ImageFileView::OnScaleMinMax (wxCommandEvent& event)
254 const ImageFile& rIF = GetDocument()->getImageFile();
256 if (! m_bMinSpecified && ! m_bMaxSpecified)
257 rIF.getMinMax (min, max);
264 DialogGetMinMax dialogMinMax (m_frame, "Set Image Minimum & Maximum", min, max);
265 int retVal = dialogMinMax.ShowModal();
266 if (retVal == wxID_OK) {
267 m_bMinSpecified = true;
268 m_bMaxSpecified = true;
269 m_dMinPixel = dialogMinMax.getMinimum();
270 m_dMaxPixel = dialogMinMax.getMaximum();
271 OnUpdate (this, NULL);
276 ImageFileView::OnCompare (wxCommandEvent& event)
\r
278 std::vector<ImageFileDocument*> vecIF;
\r
279 theApp->getCompatibleImages (GetDocument(), vecIF);
\r
281 if (vecIF.size() == 0) {
\r
282 wxMessageBox("There are no compatible image files open for comparision", "No comparison images");
\r
284 DialogGetComparisonImage dialogGetCompare(m_frame, "Get Comparison Image", vecIF, true);
\r
286 if (dialogGetCompare.ShowModal() == wxID_OK) {
\r
287 const ImageFile& rIF = GetDocument()->getImageFile();
\r
288 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
\r
289 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
\r
290 std::ostringstream os;
\r
291 double min, max, mean, mode, median, stddev;
\r
292 rIF.statistics (min, max, mean, mode, median, stddev);
\r
293 os << rIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
\r
294 rCompareIF.statistics (min, max, mean, mode, median, stddev);
\r
295 os << pCompareDoc->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
\r
298 rIF.comparativeStatistics (rCompareIF, d, r, e);
\r
299 os << "Comparative Statistics: d=" << d << ", r=" << r << ", e=" << e << "\n";
\r
300 *theApp->getLog() << os.str().c_str();
\r
301 if (dialogGetCompare.getMakeDifferenceImage()) {
\r
302 ImageFileDocument* pDifferenceDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
\r
303 if (! pDifferenceDoc) {
\r
304 sys_error (ERR_SEVERE, "Unable to create image file");
\r
307 ImageFile& differenceImage = pDifferenceDoc->getImageFile();
\r
309 differenceImage.setArraySize (rIF.nx(), rIF.ny());
\r
310 if (! rIF.subtractImages (rCompareIF, differenceImage)) {
\r
311 pDifferenceDoc->DeleteAllViews();
\r
315 if (theApp->getSetModifyNewDocs())
\r
316 pDifferenceDoc->Modify(true);
\r
317 pDifferenceDoc->UpdateAllViews(this);
\r
318 pDifferenceDoc->GetFirstView()->OnUpdate (this, NULL);
\r
320 wxMessageBox(os.str().c_str(), "Image Comparison");
\r
326 ImageFileView::OnInvertValues (wxCommandEvent& event)
\r
328 ImageFile& rIF = GetDocument()->getImageFile();
\r
329 rIF.invertPixelValues (rIF);
\r
330 if (theApp->getSetModifyNewDocs())
\r
331 GetDocument()->Modify(TRUE);
\r
332 GetDocument()->UpdateAllViews(this);
\r
336 ImageFileView::OnSquare (wxCommandEvent& event)
\r
338 ImageFile& rIF = GetDocument()->getImageFile();
\r
340 if (theApp->getSetModifyNewDocs())
\r
341 GetDocument()->Modify(TRUE);
\r
342 GetDocument()->UpdateAllViews(this);
\r
346 ImageFileView::OnSquareRoot (wxCommandEvent& event)
\r
348 ImageFile& rIF = GetDocument()->getImageFile();
\r
350 if (theApp->getSetModifyNewDocs())
\r
351 GetDocument()->Modify(TRUE);
\r
352 GetDocument()->UpdateAllViews(this);
\r
356 ImageFileView::OnLog (wxCommandEvent& event)
\r
358 ImageFile& rIF = GetDocument()->getImageFile();
\r
360 if (theApp->getSetModifyNewDocs())
\r
361 GetDocument()->Modify(TRUE);
\r
362 GetDocument()->UpdateAllViews(this);
\r
366 ImageFileView::OnExp (wxCommandEvent& event)
\r
368 ImageFile& rIF = GetDocument()->getImageFile();
\r
370 if (theApp->getSetModifyNewDocs())
\r
371 GetDocument()->Modify(TRUE);
\r
372 GetDocument()->UpdateAllViews(this);
\r
376 ImageFileView::OnFourier (wxCommandEvent& event)
\r
378 ImageFile& rIF = GetDocument()->getImageFile();
\r
379 wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);
\r
381 m_bMinSpecified = false;
\r
382 m_bMaxSpecified = false;
\r
383 if (theApp->getSetModifyNewDocs())
\r
384 GetDocument()->Modify(TRUE);
\r
385 GetDocument()->UpdateAllViews(this);
\r
390 ImageFileView::OnFFT (wxCommandEvent& event)
\r
392 ImageFile& rIF = GetDocument()->getImageFile();
\r
393 wxProgressDialog dlgProgress (wxString("FFT"), wxString("FFT Progress"), 1, m_frame, wxPD_APP_MODAL);
\r
395 m_bMinSpecified = false;
\r
396 m_bMaxSpecified = false;
\r
397 if (theApp->getSetModifyNewDocs())
\r
398 GetDocument()->Modify(TRUE);
\r
399 GetDocument()->UpdateAllViews(this);
\r
403 ImageFileView::OnIFFT (wxCommandEvent& event)
\r
405 ImageFile& rIF = GetDocument()->getImageFile();
\r
406 wxProgressDialog dlgProgress (wxString("IFFT"), wxString("IFFT Progress"), 1, m_frame, wxPD_APP_MODAL);
\r
408 m_bMinSpecified = false;
\r
409 m_bMaxSpecified = false;
\r
410 if (theApp->getSetModifyNewDocs())
\r
411 GetDocument()->Modify(TRUE);
\r
412 GetDocument()->UpdateAllViews(this);
\r
417 ImageFileView::OnInverseFourier (wxCommandEvent& event)
\r
419 ImageFile& rIF = GetDocument()->getImageFile();
\r
420 wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);
\r
421 rIF.inverseFourier (rIF);
\r
422 m_bMinSpecified = false;
\r
423 m_bMaxSpecified = false;
\r
424 if (theApp->getSetModifyNewDocs())
\r
425 GetDocument()->Modify(TRUE);
\r
426 GetDocument()->UpdateAllViews(this);
\r
430 ImageFileView::OnMagnitude (wxCommandEvent& event)
\r
432 ImageFile& rIF = GetDocument()->getImageFile();
\r
433 rIF.magnitude (rIF);
\r
434 m_bMinSpecified = false;
\r
435 m_bMaxSpecified = false;
\r
436 if (theApp->getSetModifyNewDocs())
\r
437 GetDocument()->Modify(TRUE);
\r
438 GetDocument()->UpdateAllViews(this);
\r
442 ImageFileView::OnPhase (wxCommandEvent& event)
\r
444 ImageFile& rIF = GetDocument()->getImageFile();
\r
446 m_bMinSpecified = false;
\r
447 m_bMaxSpecified = false;
\r
448 if (theApp->getSetModifyNewDocs())
\r
449 GetDocument()->Modify(TRUE);
\r
450 GetDocument()->UpdateAllViews(this);
\r
455 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
457 ImageFileCanvas* pCanvas;
459 parent->GetClientSize(&width, &height);
461 pCanvas = new ImageFileCanvas (dynamic_cast<ImageFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
463 pCanvas->SetScrollbars(20, 20, 50, 50);
464 pCanvas->SetBackgroundColour(*wxWHITE);
471 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
473 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
475 wxMenu *file_menu = new wxMenu;
477 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
\r
478 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");
\r
479 file_menu->Append(wxID_OPEN, "&Open...");
480 file_menu->Append(wxID_SAVE, "&Save");
481 file_menu->Append(wxID_SAVEAS, "Save &As...");
482 file_menu->Append(wxID_CLOSE, "&Close");
484 file_menu->AppendSeparator();
485 file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
487 file_menu->AppendSeparator();
488 file_menu->Append(wxID_PRINT, "&Print...");
489 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
490 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
492 wxMenu *view_menu = new wxMenu;
493 view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");
494 view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");
496 wxMenu* process_menu = new wxMenu;
\r
497 process_menu->Append (IFMENU_PROCESS_INVERTVALUES, "&Invert Values");
\r
498 process_menu->Append (IFMENU_PROCESS_SQUARE, "&Square");
\r
499 process_menu->Append (IFMENU_PROCESS_SQRT, "Square &Root");
\r
500 process_menu->Append (IFMENU_PROCESS_LOG, "&Log");
\r
501 process_menu->Append (IFMENU_PROCESS_EXP, "&Exp");
\r
502 process_menu->AppendSeparator();
\r
504 process_menu->Append (IFMENU_PROCESS_FFT, "&FFT");
\r
505 process_menu->Append (IFMENU_PROCESS_IFFT, "&IFFT");
\r
506 process_menu->Append (IFMENU_PROCESS_FOURIER, "F&ourier");
\r
507 process_menu->Append (IFMENU_PROCESS_INVERSE_FOURIER, "Inverse Fo&urier");
\r
509 process_menu->Append (IFMENU_PROCESS_FOURIER, "&Fourier");
\r
510 process_menu->Append (IFMENU_PROCESS_INVERSE_FOURIER, "&Inverse Fourier");
\r
512 process_menu->Append (IFMENU_PROCESS_MAGNITUDE, "&Magnitude");
\r
513 process_menu->Append (IFMENU_PROCESS_PHASE, "&Phase");
\r
515 wxMenu *plot_menu = new wxMenu;
\r
516 plot_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");
\r
517 plot_menu->Append (IFMENU_PLOT_COL, "Plot &Column");
\r
519 wxMenu *compare_menu = new wxMenu;
\r
520 compare_menu->Append (IFMENU_COMPARE_IMAGES, "Compare &Images...");
\r
521 compare_menu->Append (IFMENU_COMPARE_ROW, "Compare &Row");
\r
522 compare_menu->Append (IFMENU_COMPARE_COL, "Compare &Column");
\r
524 wxMenu *help_menu = new wxMenu;
525 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
527 wxMenuBar *menu_bar = new wxMenuBar;
529 menu_bar->Append(file_menu, "&File");
530 menu_bar->Append(view_menu, "&View");
\r
531 menu_bar->Append(process_menu, "&Process");
\r
532 menu_bar->Append(plot_menu, "P&lot");
\r
533 menu_bar->Append(compare_menu, "&Compare");
534 menu_bar->Append(help_menu, "&Help");
536 subframe->SetMenuBar(menu_bar);
538 subframe->Centre(wxBOTH);
545 ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
547 m_frame = CreateChildFrame(doc, this);
550 m_bMinSpecified = false;
551 m_bMaxSpecified = false;
552 m_dAutoScaleFactor = 1.;
555 m_frame->GetClientSize (&width, &height);
556 m_frame->SetTitle("ImageFileView");
557 m_canvas = CreateCanvas (this, m_frame);
559 int x, y; // X requires a forced resize
560 m_frame->GetSize(&x, &y);
561 m_frame->SetSize(-1, -1, x, y);
562 m_frame->SetFocus();
\r
570 ImageFileView::OnDraw (wxDC* dc)
573 dc->DrawBitmap(m_bitmap, 0, 0, false);
575 int xCursor, yCursor;
\r
576 if (m_canvas->GetCurrentCursor (xCursor, yCursor))
\r
577 m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor);
\r
582 ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
584 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
585 ImageFileArrayConst v = rIF.getArray();
588 if (v != NULL && nx != 0 && ny != 0) {
589 if (! m_bMinSpecified || ! m_bMaxSpecified) {
591 rIF.getMinMax (min, max);
592 if (! m_bMinSpecified)
594 if (! m_bMaxSpecified)
597 double scaleWidth = m_dMaxPixel - m_dMinPixel;
599 unsigned char* imageData = new unsigned char [nx * ny * 3];
600 for (int ix = 0; ix < nx; ix++) {
601 for (int iy = 0; iy < ny; iy++) {
602 double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
603 int intensity = static_cast<int>(scaleValue + 0.5);
604 intensity = clamp (intensity, 0, 255);
605 int baseAddr = ((ny - 1 - iy) * nx + ix) * 3;
606 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
609 wxImage image (nx, ny, imageData, true);
610 m_bitmap = image.ConvertToBitmap();
614 xSize = clamp (xSize, 0, 800);
615 ySize = clamp (ySize, 0, 800);
616 m_frame->SetClientSize (xSize, ySize);
617 m_canvas->SetScrollbars(20, 20, nx/20, ny/20);
618 m_canvas->SetBackgroundColour(*wxWHITE);
\r
626 ImageFileView::OnClose (bool deleteWindow)
628 if (!GetDocument()->Close())
632 m_canvas->m_pView = NULL;
634 wxString s(theApp->GetAppName());
636 m_frame->SetTitle(s);
650 ImageFileView::OnPlotRow (wxCommandEvent& event)
\r
652 int xCursor, yCursor;
\r
653 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
\r
654 wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");
\r
658 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
\r
659 ImageFileArrayConst v = rIF.getArray();
\r
663 if (v != NULL && yCursor < ny) {
\r
664 double* pX = new double [nx];
\r
665 double* pY = new double [nx];
\r
666 for (int i = 0; i < nx; i++) {
\r
668 pY[i] = v[i][yCursor];
\r
670 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
\r
672 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
\r
674 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
\r
675 std::ostringstream os;
\r
676 os << "Row " << yCursor;
\r
677 std::string title("title ");
\r
679 rPlotFile.addEzsetCommand (title.c_str());
\r
680 rPlotFile.addEzsetCommand ("xlabel Column");
\r
681 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
\r
682 rPlotFile.addEzsetCommand ("lxfrac 0");
\r
683 rPlotFile.addEzsetCommand ("box");
\r
684 rPlotFile.addEzsetCommand ("grid");
\r
685 rPlotFile.setCurveSize (2, nx);
\r
686 rPlotFile.addColumn (0, pX);
\r
687 rPlotFile.addColumn (1, pY);
\r
691 if (theApp->getSetModifyNewDocs())
\r
692 pPlotDoc->Modify(true);
\r
693 pPlotDoc->UpdateAllViews();
\r
698 ImageFileView::OnPlotCol (wxCommandEvent& event)
\r
700 int xCursor, yCursor;
\r
701 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
\r
702 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
\r
706 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
\r
707 ImageFileArrayConst v = rIF.getArray();
\r
711 if (v != NULL && xCursor < nx) {
\r
712 double* pX = new double [ny];
\r
713 double* pY = new double [ny];
\r
714 for (int i = 0; i < ny; i++) {
\r
716 pY[i] = v[xCursor][i];
\r
718 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
\r
720 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
\r
722 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
\r
723 std::ostringstream os;
\r
724 os << "Column " << xCursor;
\r
725 std::string title("title ");
\r
727 rPlotFile.addEzsetCommand (title.c_str());
\r
728 rPlotFile.addEzsetCommand ("xlabel Row");
\r
729 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
\r
730 rPlotFile.addEzsetCommand ("lxfrac 0");
\r
731 rPlotFile.addEzsetCommand ("box");
\r
732 rPlotFile.addEzsetCommand ("grid");
\r
733 rPlotFile.setCurveSize (2, nx);
\r
734 rPlotFile.addColumn (0, pX);
\r
735 rPlotFile.addColumn (1, pY);
\r
739 if (theApp->getSetModifyNewDocs())
\r
740 pPlotDoc->Modify(true);
\r
741 pPlotDoc->UpdateAllViews();
\r
746 ImageFileView::OnCompareCol (wxCommandEvent& event)
\r
748 int xCursor, yCursor;
\r
749 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
\r
750 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
\r
754 std::vector<ImageFileDocument*> vecIFDoc;
\r
755 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
\r
756 if (vecIFDoc.size() == 0) {
\r
757 wxMessageBox ("No compatible images for Column Comparison", "Error");
\r
760 DialogGetComparisonImage dialogGetCompare (m_frame, "Get Comparison Image", vecIFDoc, false);
\r
762 if (dialogGetCompare.ShowModal() == wxID_OK) {
\r
763 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
\r
764 const ImageFile& rIF = GetDocument()->getImageFile();
\r
765 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
\r
767 ImageFileArrayConst v1 = rIF.getArray();
\r
768 ImageFileArrayConst v2 = rCompareIF.getArray();
\r
772 if (v1 != NULL && xCursor < nx) {
\r
773 double* pX = new double [ny];
\r
774 double* pY1 = new double [ny];
\r
775 double* pY2 = new double [ny];
\r
776 for (int i = 0; i < ny; i++) {
\r
778 pY1[i] = v1[xCursor][i];
\r
779 pY2[i] = v2[xCursor][i];
\r
781 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
\r
783 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
\r
785 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
\r
786 std::ostringstream os;
\r
787 os << "Column " << xCursor << " Comparison";
\r
788 std::string title("title ");
\r
790 rPlotFile.addEzsetCommand (title.c_str());
\r
791 rPlotFile.addEzsetCommand ("xlabel Row");
\r
792 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
\r
793 rPlotFile.addEzsetCommand ("lxfrac 0");
\r
794 rPlotFile.addEzsetCommand ("curve 1");
\r
795 rPlotFile.addEzsetCommand ("color 2");
\r
796 rPlotFile.addEzsetCommand ("curve 2");
\r
797 rPlotFile.addEzsetCommand ("color 4");
\r
798 rPlotFile.addEzsetCommand ("dash 5");
\r
799 rPlotFile.addEzsetCommand ("box");
\r
800 rPlotFile.addEzsetCommand ("grid");
\r
801 rPlotFile.setCurveSize (3, nx);
\r
802 rPlotFile.addColumn (0, pX);
\r
803 rPlotFile.addColumn (1, pY1);
\r
804 rPlotFile.addColumn (2, pY2);
\r
809 if (theApp->getSetModifyNewDocs())
\r
810 pPlotDoc->Modify(true);
\r
811 pPlotDoc->UpdateAllViews();
\r
817 ImageFileView::OnCompareRow (wxCommandEvent& event)
\r
819 int xCursor, yCursor;
\r
820 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
\r
821 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
\r
825 std::vector<ImageFileDocument*> vecIFDoc;
\r
826 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
\r
828 if (vecIFDoc.size() == 0) {
\r
829 wxMessageBox ("No compatible images for Row Comparison", "Error");
\r
833 DialogGetComparisonImage dialogGetCompare (m_frame, "Get Comparison Image", vecIFDoc, false);
\r
835 if (dialogGetCompare.ShowModal() == wxID_OK) {
\r
836 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
\r
837 const ImageFile& rIF = GetDocument()->getImageFile();
\r
838 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
\r
840 ImageFileArrayConst v1 = rIF.getArray();
\r
841 ImageFileArrayConst v2 = rCompareIF.getArray();
\r
845 if (v1 != NULL && yCursor < ny) {
\r
846 double* pX = new double [nx];
\r
847 double* pY1 = new double [nx];
\r
848 double* pY2 = new double [nx];
\r
849 for (int i = 0; i < nx; i++) {
\r
851 pY1[i] = v1[i][yCursor];
\r
852 pY2[i] = v2[i][yCursor];
\r
854 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
\r
856 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
\r
858 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
\r
859 std::ostringstream os;
\r
860 os << "Row " << yCursor << " Comparison";
\r
861 std::string title("title ");
\r
863 rPlotFile.addEzsetCommand (title.c_str());
\r
864 rPlotFile.addEzsetCommand ("xlabel Column");
\r
865 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
\r
866 rPlotFile.addEzsetCommand ("lxfrac 0");
\r
867 rPlotFile.addEzsetCommand ("curve 1");
\r
868 rPlotFile.addEzsetCommand ("color 2");
\r
869 rPlotFile.addEzsetCommand ("curve 2");
\r
870 rPlotFile.addEzsetCommand ("color 4");
\r
871 rPlotFile.addEzsetCommand ("dash 5");
\r
872 rPlotFile.addEzsetCommand ("box");
\r
873 rPlotFile.addEzsetCommand ("grid");
\r
874 rPlotFile.setCurveSize (3, ny);
\r
875 rPlotFile.addColumn (0, pX);
\r
876 rPlotFile.addColumn (1, pY1);
\r
877 rPlotFile.addColumn (2, pY2);
\r
882 if (theApp->getSetModifyNewDocs())
\r
883 pPlotDoc->Modify(true);
\r
884 pPlotDoc->UpdateAllViews();
\r
892 PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
893 : wxScrolledWindow(frame, -1, pos, size, style)
899 PhantomCanvas::OnDraw(wxDC& dc)
902 m_pView->OnDraw(& dc);
908 IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView)
910 BEGIN_EVENT_TABLE(PhantomView, wxView)
911 EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomView::OnProperties)
912 EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomView::OnRasterize)
913 EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomView::OnProjections)
916 PhantomView::PhantomView(void)
917 : wxView(), m_canvas(NULL), m_frame(NULL)
919 m_iDefaultNDet = 367;
920 m_iDefaultNView = 320;
921 m_iDefaultNSample = 2;
922 m_dDefaultRotation = 2;
923 m_dDefaultFocalLength = 2;
924 m_dDefaultFieldOfView = 1;
925 m_iDefaultGeometry = Scanner::GEOMETRY_PARALLEL;
926 m_iDefaultTrace = Trace::TRACE_NONE;
929 PhantomView::~PhantomView(void)
934 PhantomView::OnProperties (wxCommandEvent& event)
936 const int idPhantom = GetDocument()->getPhantomID();
937 const wxString& namePhantom = GetDocument()->getPhantomName();
938 std::ostringstream os;
939 os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")\n";
940 *theApp->getLog() << os.str().c_str();
942 const Phantom& rPhantom = GetDocument()->getPhantom();
949 PhantomView::OnProjections (wxCommandEvent& event)
951 DialogGetProjectionParameters dialogProjection (m_frame, m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView, m_iDefaultGeometry, m_iDefaultTrace);
952 int retVal = dialogProjection.ShowModal();
953 if (retVal == wxID_OK) {
954 m_iDefaultNDet = dialogProjection.getNDet();
955 m_iDefaultNView = dialogProjection.getNView();
956 m_iDefaultNSample = dialogProjection.getNSamples();
957 m_iDefaultTrace = dialogProjection.getTrace();
958 m_dDefaultRotation = dialogProjection.getRotAngle();
959 m_dDefaultFocalLength = dialogProjection.getFocalLengthRatio();
960 m_dDefaultFieldOfView = dialogProjection.getFieldOfViewRatio();
961 wxString sGeometry = dialogProjection.getGeometry();
962 m_iDefaultGeometry = Scanner::convertGeometryNameToID (sGeometry.c_str());
964 if (m_iDefaultNDet > 0 && m_iDefaultNView > 0 && sGeometry != "") {
965 const Phantom& rPhantom = GetDocument()->getPhantom();
966 ProjectionFileDocument* pProjectionDoc = dynamic_cast<ProjectionFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT));
\r
967 if (! pProjectionDoc) {
\r
968 sys_error (ERR_SEVERE, "Unable to create projection document");
\r
971 Projections& rProj = pProjectionDoc->getProjections();
972 Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView);
973 if (theScanner.fail()) {
974 *theApp->getLog() << "Failed making scanner: " << theScanner.failMessage().c_str() << "\n";
977 rProj.initFromScanner (theScanner);
978 m_dDefaultRotation /= PI; // convert back to PI units
980 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
981 ProjectionsDialog dialogProjections (theScanner, rProj, rPhantom, m_iDefaultTrace, dynamic_cast<wxWindow*>(m_frame));
982 for (int iView = 0; iView < rProj.nView(); iView++) {
985 if (dialogProjections.isCancelled() || ! dialogProjections.projectView (iView)) {
986 pProjectionDoc->DeleteAllViews();
991 while (dialogProjections.isPaused()) {
997 wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), rProj.nView() + 1, m_frame, wxPD_CAN_ABORT);
998 for (int i = 0; i < rProj.nView(); i++) {
999 theScanner.collectProjections (rProj, rPhantom, i, 1, true, m_iDefaultTrace);
1000 if (! dlgProgress.Update (i+1)) {
1001 pProjectionDoc->DeleteAllViews();
1007 std::ostringstream os;
1008 os << "Projections for " << rPhantom.name() << ": nDet=" << m_iDefaultNDet << ", nView=" << m_iDefaultNView << ", nSamples=" << m_iDefaultNSample << ", RotAngle=" << m_dDefaultRotation << ", FocalLengthRatio=" << m_dDefaultFocalLength << ", FieldOfViewRatio=" << m_dDefaultFieldOfView << ", Geometry=" << sGeometry.c_str();
1009 rProj.setRemark (os.str());
1010 *theApp->getLog() << os.str().c_str() << "\n";
1014 ProjectionFileView* projView = dynamic_cast<ProjectionFileView*>(pProjectionDoc->GetFirstView());
\r
1016 projView->getFrame()->SetFocus();
\r
1017 projView->OnUpdate (projView, NULL);
\r
1019 if (wxView* pView = pProjectionDoc->GetFirstView()) {
1020 if (wxFrame* pFrame = pView->GetFrame()) {
1024 theApp->getDocManager()->ActivateView (pView, true, false);
1027 if (theApp->getSetModifyNewDocs())
\r
1028 pProjectionDoc->Modify(true);
1029 pProjectionDoc->UpdateAllViews(this);
1036 PhantomView::OnRasterize (wxCommandEvent& event)
1038 DialogGetRasterParameters dialogRaster (m_frame, 256, 256, 1);
1039 int retVal = dialogRaster.ShowModal();
1040 if (retVal == wxID_OK) {
1041 int xSize = dialogRaster.getXSize();
1042 int ySize = dialogRaster.getYSize();
1043 int nSamples = dialogRaster.getNSamples();
1046 if (xSize > 0 && ySize > 0) {
1047 const Phantom& rPhantom = GetDocument()->getPhantom();
1048 ImageFileDocument* pRasterDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
\r
1049 if (! pRasterDoc) {
\r
1050 sys_error (ERR_SEVERE, "Unable to create image file");
\r
1053 ImageFile& imageFile = pRasterDoc->getImageFile();
1055 imageFile.setArraySize (xSize, ySize);
1056 wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, m_frame, wxPD_CAN_ABORT);
1057 for (unsigned int i = 0; i < imageFile.nx(); i++) {
1058 rPhantom.convertToImagefile (imageFile, nSamples, Trace::TRACE_NONE, i, 1, true);
1059 if (! dlgProgress.Update(i+1)) {
1060 pRasterDoc->DeleteAllViews();
1064 if (theApp->getSetModifyNewDocs())
\r
1065 pRasterDoc->Modify(true);
1066 pRasterDoc->UpdateAllViews(this);
1067 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pRasterDoc->GetFirstView());
\r
1069 rasterView->getFrame()->SetFocus();
\r
1070 rasterView->OnUpdate (rasterView, NULL);
\r
1073 std::ostringstream os;
1074 os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << xSize << ", YSize=" << ySize << ", nSamples=" << nSamples << "\n";
1075 *theApp->getLog() << os.str().c_str();
1082 PhantomView::CreateCanvas (wxView *view, wxFrame *parent)
1084 PhantomCanvas* pCanvas;
1086 parent->GetClientSize(&width, &height);
1088 pCanvas = new PhantomCanvas (dynamic_cast<PhantomView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1090 pCanvas->SetBackgroundColour(*wxWHITE);
1097 PhantomView::CreateChildFrame(wxDocument *doc, wxView *view)
1099 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1101 wxMenu *file_menu = new wxMenu;
1103 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1104 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");
\r
1105 file_menu->Append(wxID_OPEN, "&Open...");
1106 file_menu->Append(wxID_CLOSE, "&Close");
1108 file_menu->AppendSeparator();
1109 file_menu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties");
1111 file_menu->AppendSeparator();
1112 file_menu->Append(wxID_PRINT, "&Print...");
1113 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1114 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1116 wxMenu *process_menu = new wxMenu;
1117 process_menu->Append(PHMMENU_PROCESS_RASTERIZE, "&Rasterize...");
1118 process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, "&Projections...");
1120 wxMenu *help_menu = new wxMenu;
1121 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1122 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1124 wxMenuBar *menu_bar = new wxMenuBar;
1126 menu_bar->Append(file_menu, "&File");
1127 menu_bar->Append(process_menu, "&Process");
1128 menu_bar->Append(help_menu, "&Help");
1130 subframe->SetMenuBar(menu_bar);
1132 subframe->Centre(wxBOTH);
1139 PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1141 m_frame = CreateChildFrame(doc, this);
1145 m_frame->GetClientSize(&width, &height);
1146 m_frame->SetTitle("PhantomView");
1147 m_canvas = CreateCanvas(this, m_frame);
1150 int x, y; // X requires a forced resize
1151 m_frame->GetSize(&x, &y);
1152 m_frame->SetSize(-1, -1, x, y);
1155 m_frame->Show(true);
1163 PhantomView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1166 m_canvas->Refresh();
1170 PhantomView::OnClose (bool deleteWindow)
1172 if (!GetDocument()->Close())
1176 m_canvas->m_pView = NULL;
1178 wxString s(wxTheApp->GetAppName());
1180 m_frame->SetTitle(s);
1193 PhantomView::OnDraw (wxDC* dc)
1196 m_canvas->GetClientSize (&xsize, &ysize);
1197 SGPDriver driver (dc, xsize, ysize);
1199 const Phantom& rPhantom = GetDocument()->getPhantom();
1200 sgp.setColor (C_RED);
1201 rPhantom.show (sgp);
1206 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1207 : wxScrolledWindow(frame, -1, pos, size, style)
1213 ProjectionFileCanvas::OnDraw(wxDC& dc)
1216 m_pView->OnDraw(& dc);
1219 // ProjectionFileView
1221 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
1223 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
1224 EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
1225 EVT_MENU(PJMENU_PROCESS_RECONSTRUCT, ProjectionFileView::OnReconstruct)
1228 ProjectionFileView::ProjectionFileView(void)
1229 : wxView(), m_canvas(NULL), m_frame(NULL)
1233 m_iDefaultFilter = SignalFilter::FILTER_ABS_BANDLIMIT;
1234 m_dDefaultFilterParam = 1.;
1236 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_RFFTW;
1237 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER;
1239 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_CONVOLUTION;
1240 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT;
1242 m_iDefaultZeropad = 1;
1243 m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF3;
1244 m_iDefaultInterpolation = Backprojector::INTERP_LINEAR;
1245 m_iDefaultInterpParam = 1;
1246 m_iDefaultTrace = Trace::TRACE_NONE;
1249 ProjectionFileView::~ProjectionFileView(void)
1254 ProjectionFileView::OnProperties (wxCommandEvent& event)
1256 const Projections& rProj = GetDocument()->getProjections();
1257 std::ostringstream os;
1258 rProj.printScanInfo(os);
1259 *theApp->getLog() << os.str().c_str();
1260 wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Projection File Properties", wxOK | wxICON_INFORMATION);
1261 dialogMsg.ShowModal();
1266 ProjectionFileView::OnReconstruct (wxCommandEvent& event)
1268 DialogGetReconstructionParameters dialogReconstruction (m_frame, m_iDefaultNX, m_iDefaultNY, m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, m_iDefaultTrace);
1270 int retVal = dialogReconstruction.ShowModal();
1271 if (retVal == wxID_OK) {
1272 m_iDefaultNX = dialogReconstruction.getXSize();
1273 m_iDefaultNY = dialogReconstruction.getYSize();
1274 wxString optFilterName = dialogReconstruction.getFilterName();
1275 m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.c_str());
1276 m_dDefaultFilterParam = dialogReconstruction.getFilterParam();
1277 wxString optFilterMethodName = dialogReconstruction.getFilterMethodName();
1278 m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.c_str());
1279 m_iDefaultZeropad = dialogReconstruction.getZeropad();
1280 wxString optFilterGenerationName = dialogReconstruction.getFilterGenerationName();
1281 m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.c_str());
1282 wxString optInterpName = dialogReconstruction.getInterpName();
1283 m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.c_str());
1284 m_iDefaultInterpParam = dialogReconstruction.getInterpParam();
1285 wxString optBackprojectName = dialogReconstruction.getBackprojectName();
1286 m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str());
1287 m_iDefaultTrace = dialogReconstruction.getTrace();
1288 if (m_iDefaultNX > 0 && m_iDefaultNY > 0) {
1289 ImageFileDocument* pReconDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
\r
1290 if (! pReconDoc) {
\r
1291 sys_error (ERR_SEVERE, "Unable to create image file");
\r
1294 ImageFile& imageFile = pReconDoc->getImageFile();
1295 const Projections& rProj = GetDocument()->getProjections();
1296 imageFile.setArraySize (m_iDefaultNX, m_iDefaultNY);
1298 if (m_iDefaultFilterMethod != ProcessSignal::FILTER_METHOD_CONVOLUTION && m_iDefaultFilterGeneration == ProcessSignal::FILTER_GENERATION_DIRECT && rProj.geometry() != Scanner::GEOMETRY_PARALLEL) {
1299 wxMessageBox ("Sorry!\nCurrently, frequency-based filtering with direct filter generation is not support for geometries other than parallel.\nAborting command.", "Not Supported", wxOK | wxICON_WARNING, m_frame);
1303 SGPDriver* pSGPDriver = NULL;
1305 wxMemoryDC* pDCPlot = NULL;
1307 if (m_iDefaultTrace >= Trace::TRACE_PLOT) {
1308 bitmap.Create (500, 500);
1309 pDCPlot = new wxMemoryDC;
1310 pDCPlot->SelectObject (bitmap);
1311 pSGPDriver = new SGPDriver (dynamic_cast<wxDC*>pDCPlot, 500, 500);
1312 pSGP = new SGP (*pSGPDriver);
1314 Reconstructor* pReconstruct = new Reconstructor (rProj, imageFile, optFilterName.c_str(), m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace, pSGP);
1317 Reconstructor* pReconstruct = new Reconstructor (rProj, imageFile, optFilterName.c_str(), m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace);
1321 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
1322 ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstruct, rProj, imageFile, m_iDefaultTrace, m_frame);
1323 for (int iView = 0; iView < rProj.nView(); iView++) {
1326 if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView)) {
1327 delete pDlgReconstruct;
1328 delete pReconstruct;
1329 pReconDoc->DeleteAllViews();
1334 while (pDlgReconstruct->isPaused()) {
1339 delete pDlgReconstruct;
1341 wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, m_frame, wxPD_CAN_ABORT);
1342 for (int i = 0; i < rProj.nView(); i++) {
1343 pReconstruct->reconstructView (i, 1);
1344 if (! dlgProgress.Update(i + 1)) {
1345 delete pReconstruct;
1346 pReconDoc->DeleteAllViews();
1351 delete pReconstruct;
1352 if (theApp->getSetModifyNewDocs())
\r
1353 pReconDoc->Modify(true);
1354 pReconDoc->UpdateAllViews(this);
1355 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pReconDoc->GetFirstView());
\r
1357 rasterView->getFrame()->SetFocus();
\r
1358 rasterView->OnUpdate (rasterView, NULL);
\r
1360 std::ostringstream os;
1361 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();
1362 *theApp->getLog() << os.str().c_str() << "\n";
1363 imageFile.labelAdd (rProj.getLabel());
1364 imageFile.labelAdd (Array2dFileLabel::L_HISTORY, os.str().c_str(), timerRecon.timerEnd());
1370 ProjectionFileCanvas*
1371 ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent)
1373 ProjectionFileCanvas* pCanvas;
1375 parent->GetClientSize(&width, &height);
1377 pCanvas = new ProjectionFileCanvas (dynamic_cast<ProjectionFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1379 pCanvas->SetScrollbars(20, 20, 50, 50);
1380 pCanvas->SetBackgroundColour(*wxWHITE);
1387 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
1389 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
1391 wxMenu *file_menu = new wxMenu;
1393 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1394 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");
\r
1395 file_menu->Append(wxID_OPEN, "&Open...");
1396 file_menu->Append(wxID_SAVE, "&Save");
1397 file_menu->Append(wxID_SAVEAS, "Save &As...");
1398 file_menu->Append(wxID_CLOSE, "&Close");
1400 file_menu->AppendSeparator();
1401 file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
1403 file_menu->AppendSeparator();
1404 file_menu->Append(wxID_PRINT, "&Print...");
1405 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1406 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1408 wxMenu *process_menu = new wxMenu;
1409 process_menu->Append(PJMENU_PROCESS_RECONSTRUCT, "R&econstruct...");
1411 wxMenu *help_menu = new wxMenu;
1412 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1413 help_menu->AppendSeparator();
1414 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1416 wxMenuBar *menu_bar = new wxMenuBar;
1418 menu_bar->Append(file_menu, "&File");
1419 menu_bar->Append(process_menu, "&Process");
1420 menu_bar->Append(help_menu, "&Help");
1422 subframe->SetMenuBar(menu_bar);
1424 subframe->Centre(wxBOTH);
1431 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1433 m_frame = CreateChildFrame(doc, this);
1437 m_frame->GetClientSize(&width, &height);
1438 m_frame->SetTitle("ProjectionFileView");
1439 m_canvas = CreateCanvas(this, m_frame);
1442 int x, y; // X requires a forced resize
1443 m_frame->GetSize(&x, &y);
1444 m_frame->SetSize(-1, -1, x, y);
1447 m_frame->Show(true);
1454 ProjectionFileView::OnDraw (wxDC* dc)
1457 dc->DrawBitmap (m_bitmap, 0, 0, false);
1462 ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1464 const Projections& rProj = GetDocument()->getProjections();
1465 const int nDet = rProj.nDet();
1466 const int nView = rProj.nView();
1467 if (nDet != 0 && nView != 0) {
1468 const DetectorArray& detarray = rProj.getDetectorArray(0);
1469 const DetectorValue* detval = detarray.detValues();
1470 double min = detval[0];
1471 double max = detval[0];
1472 for (int iy = 0; iy < nView; iy++) {
1473 const DetectorArray& detarray = rProj.getDetectorArray(iy);
1474 const DetectorValue* detval = detarray.detValues();
1475 for (int ix = 0; ix < nDet; ix++) {
1476 if (min > detval[ix])
1478 else if (max < detval[ix])
1483 unsigned char* imageData = new unsigned char [nDet * nView * 3];
1484 double scale = (max - min) / 255;
1485 for (int iy2 = 0; iy2 < nView; iy2++) {
1486 const DetectorArray& detarray = rProj.getDetectorArray (iy2);
1487 const DetectorValue* detval = detarray.detValues();
1488 for (int ix = 0; ix < nDet; ix++) {
1489 int intensity = static_cast<int>(((detval[ix] - min) / scale) + 0.5);
1490 intensity = clamp(intensity, 0, 255);
1491 int baseAddr = (iy2 * nDet + ix) * 3;
1492 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
1495 wxImage image (nDet, nView, imageData, true);
1496 m_bitmap = image.ConvertToBitmap();
1500 xSize = clamp (xSize, 0, 800);
1501 ySize = clamp (ySize, 0, 800);
1502 m_frame->SetClientSize (xSize, ySize);
1503 m_canvas->SetScrollbars (20, 20, nDet/20, nView/20);
1507 m_canvas->Refresh();
1511 ProjectionFileView::OnClose (bool deleteWindow)
1513 if (!GetDocument()->Close())
1517 m_canvas->m_pView = NULL;
1519 wxString s(wxTheApp->GetAppName());
1521 m_frame->SetTitle(s);
1536 PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1537 : wxScrolledWindow(frame, -1, pos, size, style)
1543 PlotFileCanvas::OnDraw(wxDC& dc)
1546 m_pView->OnDraw(& dc);
1552 IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
1554 BEGIN_EVENT_TABLE(PlotFileView, wxView)
1555 EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
1556 EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax)
\r
1557 EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto)
\r
1560 PlotFileView::PlotFileView(void)
1561 : wxView(), m_canvas(NULL), m_frame(NULL), m_pEZPlot(NULL)
1565 PlotFileView::~PlotFileView(void)
1572 PlotFileView::OnProperties (wxCommandEvent& event)
1574 const PlotFile& rProj = GetDocument()->getPlotFile();
1575 std::ostringstream os;
\r
1576 os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n";
1577 *theApp->getLog() << os.str().c_str();
1578 wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
1579 dialogMsg.ShowModal();
1584 PlotFileView::OnScaleAuto (wxCommandEvent& event)
\r
1586 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
\r
1587 double min, max, mean, mode, median, stddev;
\r
1588 rPlotFile.statistics (1, min, max, mean, mode, median, stddev);
\r
1589 DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor);
\r
1590 int iRetVal = dialogAutoScale.ShowModal();
\r
1591 if (iRetVal == wxID_OK) {
\r
1592 m_bMinSpecified = true;
\r
1593 m_bMaxSpecified = true;
\r
1594 double dMin, dMax;
\r
1595 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
\r
1596 m_dMinPixel = dMin;
\r
1597 m_dMaxPixel = dMax;
\r
1598 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
\r
1599 OnUpdate (this, NULL);
\r
1605 PlotFileView::OnScaleMinMax (wxCommandEvent& event)
\r
1607 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
\r
1610 if (! m_bMinSpecified && ! m_bMaxSpecified) {
\r
1611 if (! rPlotFile.getMinMax (1, min, max)) {
\r
1612 *theApp->getLog() << "Error: unable to find Min/Max\n";
\r
1617 if (m_bMinSpecified)
\r
1618 min = m_dMinPixel;
\r
1619 if (m_bMaxSpecified)
\r
1620 max = m_dMaxPixel;
\r
1622 DialogGetMinMax dialogMinMax (m_frame, "Set Y-axis Minimum & Maximum", min, max);
\r
1623 int retVal = dialogMinMax.ShowModal();
\r
1624 if (retVal == wxID_OK) {
\r
1625 m_bMinSpecified = true;
\r
1626 m_bMaxSpecified = true;
\r
1627 m_dMinPixel = dialogMinMax.getMinimum();
\r
1628 m_dMaxPixel = dialogMinMax.getMaximum();
\r
1629 OnUpdate (this, NULL);
\r
1635 PlotFileView::CreateCanvas (wxView *view, wxFrame *parent)
1637 PlotFileCanvas* pCanvas;
1639 parent->GetClientSize(&width, &height);
1641 pCanvas = new PlotFileCanvas (dynamic_cast<PlotFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1643 pCanvas->SetBackgroundColour(*wxWHITE);
1650 PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
1652 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
1654 wxMenu *file_menu = new wxMenu;
1656 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1657 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");
\r
1658 file_menu->Append(wxID_OPEN, "&Open...");
1659 file_menu->Append(wxID_SAVE, "&Save");
1660 file_menu->Append(wxID_SAVEAS, "Save &As...");
1661 file_menu->Append(wxID_CLOSE, "&Close");
1663 file_menu->AppendSeparator();
1664 file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
1666 file_menu->AppendSeparator();
1667 file_menu->Append(wxID_PRINT, "&Print...");
1668 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1669 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1671 wxMenu *view_menu = new wxMenu;
\r
1672 view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");
\r
1673 view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");
\r
1675 wxMenu *help_menu = new wxMenu;
1676 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1677 help_menu->AppendSeparator();
1678 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1680 wxMenuBar *menu_bar = new wxMenuBar;
1682 menu_bar->Append(file_menu, "&File");
\r
1683 menu_bar->Append(view_menu, "&View");
1684 menu_bar->Append(help_menu, "&Help");
1686 subframe->SetMenuBar(menu_bar);
1688 subframe->Centre(wxBOTH);
1695 PlotFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
1697 m_frame = CreateChildFrame(doc, this);
1700 m_bMinSpecified = false;
\r
1701 m_bMaxSpecified = false;
\r
1702 m_dAutoScaleFactor = 1.;
\r
1705 m_frame->GetClientSize(&width, &height);
1706 m_frame->SetTitle ("Plot File");
1707 m_canvas = CreateCanvas (this, m_frame);
1710 int x, y; // X requires a forced resize
1711 m_frame->GetSize(&x, &y);
1712 m_frame->SetSize(-1, -1, x, y);
1715 m_frame->Show(true);
1722 PlotFileView::OnDraw (wxDC* dc)
1724 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
\r
1725 const int iNColumns = rPlotFile.getNumColumns();
\r
1726 const int iNRecords = rPlotFile.getNumRecords();
\r
1728 if (iNColumns > 0 && iNRecords > 0) {
\r
1730 m_canvas->GetClientSize (&xsize, &ysize);
\r
1731 SGPDriver driver (dc, xsize, ysize);
\r
1734 m_pEZPlot->plot (&sgp);
\r
1740 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1743 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
\r
1744 const int iNColumns = rPlotFile.getNumColumns();
\r
1745 const int iNRecords = rPlotFile.getNumRecords();
\r
1747 if (iNColumns > 0 && iNRecords > 0) {
\r
1750 m_pEZPlot = new EZPlot;
\r
1752 for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)
\r
1753 m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));
\r
1755 if (m_bMinSpecified) {
\r
1756 std::ostringstream os;
\r
1757 os << "ymin " << m_dMinPixel;
\r
1758 m_pEZPlot->ezset (os.str());
\r
1761 if (m_bMaxSpecified) {
\r
1762 std::ostringstream os;
\r
1763 os << "ymax " << m_dMaxPixel;
\r
1764 m_pEZPlot->ezset (os.str());
\r
1767 m_pEZPlot->ezset("box");
\r
1768 m_pEZPlot->ezset("grid");
\r
1770 double* pdXaxis = new double [iNRecords];
\r
1771 rPlotFile.getColumn (0, pdXaxis);
\r
1773 double* pdY = new double [iNRecords];
\r
1774 for (int iCol = 1; iCol < iNColumns; iCol++) {
\r
1775 rPlotFile.getColumn (iCol, pdY);
\r
1776 m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords);
\r
1783 m_canvas->Refresh();
\r
1788 PlotFileView::OnClose (bool deleteWindow)
1790 if (!GetDocument()->Close())
1794 m_canvas->m_pView = NULL;
1796 wxString s(wxTheApp->GetAppName());
1798 m_frame->SetTitle(s);