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.68 2001/01/20 08:10:33 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
60 #include <sstream_subst>
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)
89 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
94 dc.SetLogicalFunction (wxINVERT);
95 dc.SetPen (*wxGREEN_PEN);
96 dc.DrawLine (0, yPt, nx, yPt);
97 dc.DrawLine (x, 0, x, ny);
98 dc.SetLogicalFunction (wxCOPY);
102 ImageFileCanvas::GetCurrentCursor (int& x, int& y)
107 if (m_xCursor >= 0 && m_yCursor >= 0)
114 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
122 wxPoint pt(event.GetLogicalPosition(dc));
124 const ImageFileDocument* pIFDoc = m_pView->GetDocument();
127 const ImageFile& rIF = pIFDoc->getImageFile();
128 ImageFileArrayConst v = rIF.getArray();
131 const int yPt = ny - 1 - pt.y;
132 if (event.RightIsDown()) {
133 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
134 std::ostringstream os;
135 os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt];
136 if (rIF.isComplex()) {
137 double dImag = rIF.getImaginaryArray()[pt.x][yPt];
139 os << " - " << -dImag;
141 os << " + " << dImag;
145 *theApp->getLog() << os.str().c_str();
147 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
149 else if (event.LeftIsDown() || event.LeftUp() || event.RightUp()) {
150 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
151 if (m_xCursor >= 0 && m_yCursor >= 0) {
152 DrawRubberBandCursor (dc, m_xCursor, m_yCursor);
154 DrawRubberBandCursor (dc, pt.x, yPt);
158 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
160 if (event.LeftUp()) {
161 std::ostringstream os;
162 os << "Selected column " << pt.x << " , row " << yPt << "\n";
163 *theApp->getLog() << os.str().c_str();
168 ImageFileCanvas::GetBestSize() const
173 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
174 return wxSize (rIF.nx(), rIF.ny());
180 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
182 BEGIN_EVENT_TABLE(ImageFileView, wxView)
183 EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
184 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
185 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
186 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
187 EVT_MENU(IFMENU_VIEW_SCALE_FULL, ImageFileView::OnScaleFull)
188 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)
189 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)
190 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)
191 EVT_MENU(IFMENU_FILTER_INVERTVALUES, ImageFileView::OnInvertValues)
192 EVT_MENU(IFMENU_FILTER_SQUARE, ImageFileView::OnSquare)
193 EVT_MENU(IFMENU_FILTER_SQRT, ImageFileView::OnSquareRoot)
194 EVT_MENU(IFMENU_FILTER_LOG, ImageFileView::OnLog)
195 EVT_MENU(IFMENU_FILTER_EXP, ImageFileView::OnExp)
196 EVT_MENU(IFMENU_FILTER_FOURIER, ImageFileView::OnFourier)
197 EVT_MENU(IFMENU_FILTER_INVERSE_FOURIER, ImageFileView::OnInverseFourier)
198 EVT_MENU(IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)
199 EVT_MENU(IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)
200 EVT_MENU(IFMENU_IMAGE_ADD, ImageFileView::OnAdd)
201 EVT_MENU(IFMENU_IMAGE_SUBTRACT, ImageFileView::OnSubtract)
202 EVT_MENU(IFMENU_IMAGE_MULTIPLY, ImageFileView::OnMultiply)
203 EVT_MENU(IFMENU_IMAGE_DIVIDE, ImageFileView::OnDivide)
204 EVT_MENU(IFMENU_IMAGE_SCALESIZE, ImageFileView::OnScaleSize)
206 EVT_MENU(IFMENU_FILTER_FFT, ImageFileView::OnFFT)
207 EVT_MENU(IFMENU_FILTER_IFFT, ImageFileView::OnIFFT)
208 EVT_MENU(IFMENU_FILTER_FFT_ROWS, ImageFileView::OnFFTRows)
209 EVT_MENU(IFMENU_FILTER_IFFT_ROWS, ImageFileView::OnIFFTRows)
210 EVT_MENU(IFMENU_FILTER_FFT_COLS, ImageFileView::OnFFTCols)
211 EVT_MENU(IFMENU_FILTER_IFFT_COLS, ImageFileView::OnIFFTCols)
213 EVT_MENU(IFMENU_FILTER_MAGNITUDE, ImageFileView::OnMagnitude)
214 EVT_MENU(IFMENU_FILTER_PHASE, ImageFileView::OnPhase)
215 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)
216 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)
218 EVT_MENU(IFMENU_PLOT_FFT_ROW, ImageFileView::OnPlotFFTRow)
219 EVT_MENU(IFMENU_PLOT_FFT_COL, ImageFileView::OnPlotFFTCol)
221 EVT_MENU(IFMENU_PLOT_HISTOGRAM, ImageFileView::OnPlotHistogram)
224 ImageFileView::ImageFileView(void)
225 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
227 m_iDefaultExportFormatID = ImageFile::FORMAT_PNG;
230 ImageFileView::~ImageFileView(void)
235 ImageFileView::OnProperties (wxCommandEvent& event)
237 const ImageFile& rIF = GetDocument()->getImageFile();
238 if (rIF.nx() == 0 || rIF.ny() == 0)
239 *theApp->getLog() << "Properties: empty imagefile\n";
241 const std::string& rFilename = rIF.getFilename();
242 std::ostringstream os;
243 double min, max, mean, mode, median, stddev;
244 rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);
245 os << "Filename: " << rFilename << "\n";
246 os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";
252 os << "\nMinimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
253 if (rIF.isComplex()) {
254 rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);
255 os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";
257 if (rIF.nLabels() > 0) {
259 rIF.printLabelsBrief (os);
261 *theApp->getLog() << os.str().c_str();
262 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
263 dialogMsg.ShowModal();
268 ImageFileView::OnScaleAuto (wxCommandEvent& event)
270 const ImageFile& rIF = GetDocument()->getImageFile();
271 double min, max, mean, mode, median, stddev;
272 rIF.statistics(min, max, mean, mode, median, stddev);
273 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
274 int iRetVal = dialogAutoScale.ShowModal();
275 if (iRetVal == wxID_OK) {
276 m_bMinSpecified = true;
277 m_bMaxSpecified = true;
279 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
282 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
283 OnUpdate (this, NULL);
289 ImageFileView::OnScaleMinMax (wxCommandEvent& event)
291 const ImageFile& rIF = GetDocument()->getImageFile();
293 if (! m_bMinSpecified && ! m_bMaxSpecified)
294 rIF.getMinMax (min, max);
301 DialogGetMinMax dialogMinMax (getFrameForChild(), "Set Image Minimum & Maximum", min, max);
302 int retVal = dialogMinMax.ShowModal();
303 if (retVal == wxID_OK) {
304 m_bMinSpecified = true;
305 m_bMaxSpecified = true;
306 m_dMinPixel = dialogMinMax.getMinimum();
307 m_dMaxPixel = dialogMinMax.getMaximum();
308 OnUpdate (this, NULL);
313 ImageFileView::OnScaleFull (wxCommandEvent& event)
315 if (m_bMinSpecified || m_bMaxSpecified) {
316 m_bMinSpecified = false;
317 m_bMaxSpecified = false;
318 OnUpdate (this, NULL);
323 ImageFileView::OnCompare (wxCommandEvent& event)
325 std::vector<ImageFileDocument*> vecIF;
326 theApp->getCompatibleImages (GetDocument(), vecIF);
328 if (vecIF.size() == 0) {
329 wxMessageBox("There are no compatible image files open for comparision", "No comparison images");
331 DialogGetComparisonImage dialogGetCompare(getFrameForChild(), "Get Comparison Image", vecIF, true);
333 if (dialogGetCompare.ShowModal() == wxID_OK) {
334 const ImageFile& rIF = GetDocument()->getImageFile();
335 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
336 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
337 std::ostringstream os;
338 double min, max, mean, mode, median, stddev;
339 rIF.statistics (min, max, mean, mode, median, stddev);
340 os << GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
341 rCompareIF.statistics (min, max, mean, mode, median, stddev);
342 os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
345 rIF.comparativeStatistics (rCompareIF, d, r, e);
346 os << "Comparative Statistics: d=" << d << ", r=" << r << ", e=" << e << "\n";
347 *theApp->getLog() << os.str().c_str();
348 if (dialogGetCompare.getMakeDifferenceImage()) {
349 ImageFileDocument* pDifferenceDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
350 if (! pDifferenceDoc) {
351 sys_error (ERR_SEVERE, "Unable to create image file");
354 ImageFile& differenceImage = pDifferenceDoc->getImageFile();
356 differenceImage.setArraySize (rIF.nx(), rIF.ny());
357 if (! rIF.subtractImages (rCompareIF, differenceImage)) {
358 pDifferenceDoc->DeleteAllViews();
362 wxString s = GetFrame()->GetTitle() + ": ";
363 differenceImage.labelsCopy (rIF, s.c_str());
364 s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
365 differenceImage.labelsCopy (rCompareIF, s.c_str());
366 std::ostringstream osLabel;
367 osLabel << "Compare image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str()
368 << " and " << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": "
370 differenceImage.labelAdd (os.str().c_str());
371 if (theApp->getSetModifyNewDocs())
372 pDifferenceDoc->Modify(true);
373 pDifferenceDoc->UpdateAllViews(this);
374 pDifferenceDoc->GetFirstView()->OnUpdate (this, NULL);
376 wxMessageBox(os.str().c_str(), "Image Comparison");
382 ImageFileView::OnInvertValues (wxCommandEvent& event)
384 ImageFile& rIF = GetDocument()->getImageFile();
385 rIF.invertPixelValues (rIF);
386 rIF.labelAdd ("Invert Pixel Values");
387 if (theApp->getSetModifyNewDocs())
388 GetDocument()->Modify(TRUE);
389 GetDocument()->UpdateAllViews(this);
393 ImageFileView::OnSquare (wxCommandEvent& event)
395 ImageFile& rIF = GetDocument()->getImageFile();
397 rIF.labelAdd ("Square Pixel Values");
398 if (theApp->getSetModifyNewDocs())
399 GetDocument()->Modify(TRUE);
400 GetDocument()->UpdateAllViews(this);
404 ImageFileView::OnSquareRoot (wxCommandEvent& event)
406 ImageFile& rIF = GetDocument()->getImageFile();
408 rIF.labelAdd ("Square-root Pixel Values");
409 if (theApp->getSetModifyNewDocs())
410 GetDocument()->Modify(TRUE);
411 GetDocument()->UpdateAllViews(this);
415 ImageFileView::OnLog (wxCommandEvent& event)
417 ImageFile& rIF = GetDocument()->getImageFile();
419 rIF.labelAdd ("Logrithm base-e Pixel Values");
420 if (theApp->getSetModifyNewDocs())
421 GetDocument()->Modify(TRUE);
422 GetDocument()->UpdateAllViews(this);
426 ImageFileView::OnExp (wxCommandEvent& event)
428 ImageFile& rIF = GetDocument()->getImageFile();
430 rIF.labelAdd ("Exponent base-e Pixel Values");
431 if (theApp->getSetModifyNewDocs())
432 GetDocument()->Modify(TRUE);
433 GetDocument()->UpdateAllViews(this);
437 ImageFileView::OnAdd (wxCommandEvent& event)
439 std::vector<ImageFileDocument*> vecIF;
440 theApp->getCompatibleImages (GetDocument(), vecIF);
442 if (vecIF.size() == 0) {
443 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
445 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Add", vecIF, false);
447 if (dialogGetCompare.ShowModal() == wxID_OK) {
448 ImageFile& rIF = GetDocument()->getImageFile();
449 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
450 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
451 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
453 sys_error (ERR_SEVERE, "Unable to create image file");
456 ImageFile& newImage = pNewDoc->getImageFile();
457 newImage.setArraySize (rIF.nx(), rIF.ny());
458 rIF.addImages (rRHSIF, newImage);
459 std::ostringstream os;
460 os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
461 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
462 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
463 newImage.labelsCopy (rIF, s.c_str());
464 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
465 newImage.labelsCopy (rRHSIF, s.c_str());
466 newImage.labelAdd (os.str().c_str());
467 *theApp->getLog() << os.str().c_str() << "\n";
468 if (theApp->getSetModifyNewDocs())
469 pNewDoc->Modify(TRUE);
470 pNewDoc->UpdateAllViews(this);
471 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
477 ImageFileView::OnSubtract (wxCommandEvent& event)
479 std::vector<ImageFileDocument*> vecIF;
480 theApp->getCompatibleImages (GetDocument(), vecIF);
482 if (vecIF.size() == 0) {
483 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
485 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Subtract", vecIF, false);
487 if (dialogGetCompare.ShowModal() == wxID_OK) {
488 ImageFile& rIF = GetDocument()->getImageFile();
489 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
490 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
491 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
493 sys_error (ERR_SEVERE, "Unable to create image file");
496 ImageFile& newImage = pNewDoc->getImageFile();
497 newImage.setArraySize (rIF.nx(), rIF.ny());
498 rIF.subtractImages (rRHSIF, newImage);
499 std::ostringstream os;
500 os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
501 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
502 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
503 newImage.labelsCopy (rIF, s.c_str());
504 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
505 newImage.labelsCopy (rRHSIF, s.c_str());
506 newImage.labelAdd (os.str().c_str());
507 *theApp->getLog() << os.str().c_str() << "\n";
508 if (theApp->getSetModifyNewDocs())
509 pNewDoc->Modify(TRUE);
510 pNewDoc->UpdateAllViews(this);
511 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
517 ImageFileView::OnMultiply (wxCommandEvent& event)
519 std::vector<ImageFileDocument*> vecIF;
520 theApp->getCompatibleImages (GetDocument(), vecIF);
522 if (vecIF.size() == 0) {
523 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
525 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Multiply", vecIF, false);
527 if (dialogGetCompare.ShowModal() == wxID_OK) {
528 ImageFile& rIF = GetDocument()->getImageFile();
529 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
530 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
531 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
533 sys_error (ERR_SEVERE, "Unable to create image file");
536 ImageFile& newImage = pNewDoc->getImageFile();
537 newImage.setArraySize (rIF.nx(), rIF.ny());
538 rIF.multiplyImages (rRHSIF, newImage);
539 std::ostringstream os;
540 os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
541 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
542 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
543 newImage.labelsCopy (rIF, s.c_str());
544 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
545 newImage.labelsCopy (rRHSIF, s.c_str());
546 newImage.labelAdd (os.str().c_str());
547 *theApp->getLog() << os.str().c_str() << "\n";
548 if (theApp->getSetModifyNewDocs())
549 pNewDoc->Modify(TRUE);
550 pNewDoc->UpdateAllViews(this);
551 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
557 ImageFileView::OnDivide (wxCommandEvent& event)
559 std::vector<ImageFileDocument*> vecIF;
560 theApp->getCompatibleImages (GetDocument(), vecIF);
562 if (vecIF.size() == 0) {
563 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
565 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Divide", vecIF, false);
567 if (dialogGetCompare.ShowModal() == wxID_OK) {
568 ImageFile& rIF = GetDocument()->getImageFile();
569 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
570 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
571 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
573 sys_error (ERR_SEVERE, "Unable to create image file");
576 ImageFile& newImage = pNewDoc->getImageFile();
577 newImage.setArraySize (rIF.nx(), rIF.ny());
578 rIF.divideImages (rRHSIF, newImage);
579 std::ostringstream os;
580 os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " by "
581 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
582 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
583 newImage.labelsCopy (rIF, s.c_str());
584 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
585 newImage.labelsCopy (rRHSIF, s.c_str());
586 newImage.labelAdd (os.str().c_str());
587 *theApp->getLog() << os.str().c_str() << "\n";
588 if (theApp->getSetModifyNewDocs())
589 pNewDoc->Modify(TRUE);
590 pNewDoc->UpdateAllViews(this);
591 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
599 ImageFileView::OnFFT (wxCommandEvent& event)
601 ImageFile& rIF = GetDocument()->getImageFile();
603 rIF.labelAdd ("FFT Image");
604 m_bMinSpecified = false;
605 m_bMaxSpecified = false;
606 if (theApp->getSetModifyNewDocs())
607 GetDocument()->Modify(TRUE);
608 GetDocument()->UpdateAllViews(this);
612 ImageFileView::OnIFFT (wxCommandEvent& event)
614 ImageFile& rIF = GetDocument()->getImageFile();
616 rIF.labelAdd ("IFFT Image");
617 m_bMinSpecified = false;
618 m_bMaxSpecified = false;
619 if (theApp->getSetModifyNewDocs())
620 GetDocument()->Modify(TRUE);
621 GetDocument()->UpdateAllViews(this);
625 ImageFileView::OnFFTRows (wxCommandEvent& event)
627 ImageFile& rIF = GetDocument()->getImageFile();
629 rIF.labelAdd ("FFT Rows");
630 m_bMinSpecified = false;
631 m_bMaxSpecified = false;
632 if (theApp->getSetModifyNewDocs())
633 GetDocument()->Modify(TRUE);
634 GetDocument()->UpdateAllViews(this);
638 ImageFileView::OnIFFTRows (wxCommandEvent& event)
640 ImageFile& rIF = GetDocument()->getImageFile();
642 rIF.labelAdd ("IFFT Rows");
643 m_bMinSpecified = false;
644 m_bMaxSpecified = false;
645 if (theApp->getSetModifyNewDocs())
646 GetDocument()->Modify(TRUE);
647 GetDocument()->UpdateAllViews(this);
651 ImageFileView::OnFFTCols (wxCommandEvent& event)
653 ImageFile& rIF = GetDocument()->getImageFile();
655 rIF.labelAdd ("FFT Columns");
656 m_bMinSpecified = false;
657 m_bMaxSpecified = false;
658 if (theApp->getSetModifyNewDocs())
659 GetDocument()->Modify(TRUE);
660 GetDocument()->UpdateAllViews(this);
664 ImageFileView::OnIFFTCols (wxCommandEvent& event)
666 ImageFile& rIF = GetDocument()->getImageFile();
668 rIF.labelAdd ("IFFT Columns");
669 m_bMinSpecified = false;
670 m_bMaxSpecified = false;
671 if (theApp->getSetModifyNewDocs())
672 GetDocument()->Modify(TRUE);
673 GetDocument()->UpdateAllViews(this);
678 ImageFileView::OnFourier (wxCommandEvent& event)
680 ImageFile& rIF = GetDocument()->getImageFile();
681 wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
683 rIF.labelAdd ("Fourier Image");
684 m_bMinSpecified = false;
685 m_bMaxSpecified = false;
686 if (theApp->getSetModifyNewDocs())
687 GetDocument()->Modify(TRUE);
688 GetDocument()->UpdateAllViews(this);
692 ImageFileView::OnInverseFourier (wxCommandEvent& event)
694 ImageFile& rIF = GetDocument()->getImageFile();
695 wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
696 rIF.inverseFourier (rIF);
697 rIF.labelAdd ("Inverse Fourier Image");
698 m_bMinSpecified = false;
699 m_bMaxSpecified = false;
700 if (theApp->getSetModifyNewDocs())
701 GetDocument()->Modify(TRUE);
702 GetDocument()->UpdateAllViews(this);
706 ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)
708 ImageFile& rIF = GetDocument()->getImageFile();
709 Fourier::shuffleNaturalToFourierOrder (rIF);
710 rIF.labelAdd ("Shuffle Natural To Fourier Order");
711 m_bMinSpecified = false;
712 m_bMaxSpecified = false;
713 if (theApp->getSetModifyNewDocs())
714 GetDocument()->Modify(TRUE);
715 GetDocument()->UpdateAllViews(this);
719 ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)
721 ImageFile& rIF = GetDocument()->getImageFile();
722 Fourier::shuffleFourierToNaturalOrder (rIF);
723 rIF.labelAdd ("Shuffle Fourier To Natural Order");
724 m_bMinSpecified = false;
725 m_bMaxSpecified = false;
726 if (theApp->getSetModifyNewDocs())
727 GetDocument()->Modify(TRUE);
728 GetDocument()->UpdateAllViews(this);
732 ImageFileView::OnMagnitude (wxCommandEvent& event)
734 ImageFile& rIF = GetDocument()->getImageFile();
735 if (rIF.isComplex()) {
737 rIF.labelAdd ("Magnitude of complex-image");
738 m_bMinSpecified = false;
739 m_bMaxSpecified = false;
740 if (theApp->getSetModifyNewDocs())
741 GetDocument()->Modify(TRUE);
742 GetDocument()->UpdateAllViews(this);
747 ImageFileView::OnPhase (wxCommandEvent& event)
749 ImageFile& rIF = GetDocument()->getImageFile();
750 if (rIF.isComplex()) {
752 rIF.labelAdd ("Phase of complex-image");
753 m_bMinSpecified = false;
754 m_bMaxSpecified = false;
755 if (theApp->getSetModifyNewDocs())
756 GetDocument()->Modify(TRUE);
757 GetDocument()->UpdateAllViews(this);
763 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
765 ImageFileCanvas* pCanvas;
767 parent->GetClientSize(&width, &height);
769 pCanvas = new ImageFileCanvas (dynamic_cast<ImageFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
771 pCanvas->SetScrollbars(20, 20, 50, 50);
772 pCanvas->SetBackgroundColour(*wxWHITE);
779 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
782 wxDocMDIChildFrame* subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
784 wxDocChildFrame* subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
786 theApp->setIconForFrame (subframe);
788 wxMenu *file_menu = new wxMenu;
790 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
791 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
792 file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
793 file_menu->Append(wxID_SAVE, "&Save\tCtrl-S");
794 file_menu->Append(wxID_SAVEAS, "Save &As...");
795 file_menu->Append(wxID_CLOSE, "&Close\tCtrl-W");
797 file_menu->AppendSeparator();
798 file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
799 file_menu->Append(IFMENU_FILE_EXPORT, "&Export...");
801 file_menu->AppendSeparator();
802 file_menu->Append(wxID_PRINT, "&Print...");
803 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
804 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
806 wxMenu *view_menu = new wxMenu;
807 view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale S&et...\tCtrl-E");
808 view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...\tCtrl-A");
809 view_menu->Append(IFMENU_VIEW_SCALE_FULL, "Display F&ull Scale\tCtrl-U");
811 wxMenu* filter_menu = new wxMenu;
812 filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");
813 filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");
814 filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");
815 filter_menu->Append (IFMENU_FILTER_LOG, "&Log");
816 filter_menu->Append (IFMENU_FILTER_EXP, "&Exp");
817 filter_menu->AppendSeparator();
819 filter_menu->Append (IFMENU_FILTER_FFT, "2D &FFT");
820 filter_menu->Append (IFMENU_FILTER_IFFT, "2D &IFFT");
821 filter_menu->Append (IFMENU_FILTER_FFT_ROWS, "FFT Rows");
822 filter_menu->Append (IFMENU_FILTER_IFFT_ROWS, "IFFT Rows");
823 filter_menu->Append (IFMENU_FILTER_FFT_COLS, "FFT Columns");
824 filter_menu->Append (IFMENU_FILTER_IFFT_COLS, "IFFT Columns");
825 filter_menu->Append (IFMENU_FILTER_FOURIER, "F&ourier");
826 filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "Inverse Fo&urier");
828 filter_menu->Append (IFMENU_FILTER_FOURIER, "&Fourier");
829 filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "&Inverse Fourier");
831 filter_menu->Append (IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order");
832 filter_menu->Append (IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order");
833 filter_menu->Append (IFMENU_FILTER_MAGNITUDE, "&Magnitude");
834 filter_menu->Append (IFMENU_FILTER_PHASE, "&Phase");
836 wxMenu* image_menu = new wxMenu;
837 image_menu->Append (IFMENU_IMAGE_ADD, "&Add...");
838 image_menu->Append (IFMENU_IMAGE_SUBTRACT, "&Subtract...");
839 image_menu->Append (IFMENU_IMAGE_MULTIPLY, "&Multiply...");
840 image_menu->Append (IFMENU_IMAGE_DIVIDE, "&Divide...");
841 image_menu->AppendSeparator();
842 image_menu->Append (IFMENU_IMAGE_SCALESIZE, "S&cale Size...");
844 wxMenu *analyze_menu = new wxMenu;
845 analyze_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");
846 analyze_menu->Append (IFMENU_PLOT_COL, "Plot &Column");
847 analyze_menu->Append (IFMENU_PLOT_HISTOGRAM, "Plot &Histogram");
848 analyze_menu->AppendSeparator();
849 analyze_menu->Append (IFMENU_PLOT_FFT_ROW, "Plot FFT Row");
850 analyze_menu->Append (IFMENU_PLOT_FFT_COL, "Plot FFT Column");
851 analyze_menu->AppendSeparator();
852 analyze_menu->Append (IFMENU_COMPARE_IMAGES, "Compare &Images...");
853 analyze_menu->Append (IFMENU_COMPARE_ROW, "Compare &Row");
854 analyze_menu->Append (IFMENU_COMPARE_COL, "Compare &Column");
856 wxMenu *help_menu = new wxMenu;
857 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
858 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
859 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
861 wxMenuBar *menu_bar = new wxMenuBar;
863 menu_bar->Append(file_menu, "&File");
864 menu_bar->Append(view_menu, "&View");
865 menu_bar->Append(image_menu, "&Image");
866 menu_bar->Append(filter_menu, "Fi<er");
867 menu_bar->Append(analyze_menu, "&Analyze");
868 menu_bar->Append(help_menu, "&Help");
870 subframe->SetMenuBar(menu_bar);
872 subframe->Centre(wxBOTH);
874 wxAcceleratorEntry accelEntries[10];
875 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
876 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
877 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
878 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
879 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
880 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
881 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
882 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('A'), IFMENU_VIEW_SCALE_AUTO);
883 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('U'), IFMENU_VIEW_SCALE_FULL);
884 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('E'), IFMENU_VIEW_SCALE_MINMAX);
885 wxAcceleratorTable accelTable (10, accelEntries);
886 subframe->SetAcceleratorTable (accelTable);
893 ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
895 m_frame = CreateChildFrame(doc, this);
898 m_bMinSpecified = false;
899 m_bMaxSpecified = false;
900 m_dAutoScaleFactor = 1.;
903 m_frame->GetClientSize (&width, &height);
904 m_frame->SetTitle("ImageFileView");
905 m_canvas = CreateCanvas (this, m_frame);
907 int x, y; // X requires a forced resize
908 m_frame->GetSize(&x, &y);
909 m_frame->SetSize(-1, -1, x, y);
918 ImageFileView::OnDraw (wxDC* dc)
920 wxSize sizeWindow = m_frame->GetClientSize();
921 wxSize sizeBest = m_canvas->GetBestSize();
922 if (sizeWindow.x > sizeBest.x || sizeWindow.y > sizeBest.y)
923 m_frame->SetClientSize (sizeBest);
926 dc->DrawBitmap(m_bitmap, 0, 0, false);
928 int xCursor, yCursor;
929 if (m_canvas->GetCurrentCursor (xCursor, yCursor))
930 m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor);
935 ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
937 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
938 ImageFileArrayConst v = rIF.getArray();
941 if (v != NULL && nx != 0 && ny != 0) {
942 if (! m_bMinSpecified || ! m_bMaxSpecified) {
944 rIF.getMinMax (min, max);
945 if (! m_bMinSpecified)
947 if (! m_bMaxSpecified)
950 double scaleWidth = m_dMaxPixel - m_dMinPixel;
952 unsigned char* imageData = new unsigned char [nx * ny * 3];
953 for (int ix = 0; ix < nx; ix++) {
954 for (int iy = 0; iy < ny; iy++) {
955 double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
956 int intensity = static_cast<int>(scaleValue + 0.5);
957 intensity = clamp (intensity, 0, 255);
958 int baseAddr = ((ny - 1 - iy) * nx + ix) * 3;
959 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
962 wxImage image (nx, ny, imageData, true);
963 m_bitmap = image.ConvertToBitmap();
967 xSize = clamp (xSize, 0, 800);
968 ySize = clamp (ySize, 0, 800);
969 m_frame->SetClientSize (xSize, ySize);
970 m_canvas->SetScrollbars(20, 20, nx/20, ny/20);
971 m_canvas->SetBackgroundColour(*wxWHITE);
979 ImageFileView::OnClose (bool deleteWindow)
981 if (!GetDocument()->Close())
985 //m_canvas->m_pView = NULL;
987 wxString s(theApp->GetAppName());
989 m_frame->SetTitle(s);
1002 ImageFileView::OnExport (wxCommandEvent& event)
1004 ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1005 ImageFileArrayConst v = rIF.getArray();
1008 if (v != NULL && nx != 0 && ny != 0) {
1009 if (! m_bMinSpecified || ! m_bMaxSpecified) {
1011 rIF.getMinMax (min, max);
1012 if (! m_bMinSpecified)
1014 if (! m_bMaxSpecified)
1018 DialogExportParameters dialogExport (getFrameForChild(), m_iDefaultExportFormatID);
1019 if (dialogExport.ShowModal() == wxID_OK) {
1020 wxString strFormatName (dialogExport.getFormatName ());
1021 m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str());
1024 wxString strWildcard;
1025 if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) {
1027 strWildcard = "PGM Files (*.pgm)|*.pgm";
1030 else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) {
1032 strWildcard = "PNG Files (*.png)|*.png";
1036 const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""),
1037 wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);
1039 rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel);
1040 *theApp->getLog() << "Exported file " << strFilename << "\n";
1047 ImageFileView::OnScaleSize (wxCommandEvent& event)
1049 ImageFile& rIF = GetDocument()->getImageFile();
1050 unsigned int iOldNX = rIF.nx();
1051 unsigned int iOldNY = rIF.ny();
1053 DialogGetXYSize dialogGetXYSize (getFrameForChild(), "Set New X & Y Dimensions", iOldNX, iOldNY);
1054 if (dialogGetXYSize.ShowModal() == wxID_OK) {
1055 unsigned int iNewNX = dialogGetXYSize.getXSize();
1056 unsigned int iNewNY = dialogGetXYSize.getYSize();
1057 std::ostringstream os;
1058 os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";
1059 ImageFileDocument* pScaledDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
1061 sys_error (ERR_SEVERE, "Unable to create image file");
1064 ImageFile& rScaledIF = pScaledDoc->getImageFile();
1065 rScaledIF.setArraySize (iNewNX, iNewNY);
1066 rScaledIF.labelsCopy (rIF);
1067 rScaledIF.labelAdd (os.str().c_str());
1068 rIF.scaleImage (rScaledIF);
1069 *theApp->getLog() << os.str().c_str() << "\n";
1070 if (theApp->getSetModifyNewDocs())
1071 pScaledDoc->Modify(TRUE);
1072 pScaledDoc->UpdateAllViews (this);
1073 pScaledDoc->GetFirstView()->OnUpdate (this, NULL);
1078 ImageFileView::OnPlotRow (wxCommandEvent& event)
1080 int xCursor, yCursor;
1081 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1082 wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");
1086 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1087 ImageFileArrayConst v = rIF.getArray();
1088 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1092 if (v != NULL && yCursor < ny) {
1093 double* pX = new double [nx];
1094 double* pYReal = new double [nx];
1095 double *pYImag = NULL;
1096 double *pYMag = NULL;
1097 if (rIF.isComplex()) {
1098 pYImag = new double [nx];
1099 pYMag = new double [nx];
1101 for (int i = 0; i < nx; i++) {
1103 pYReal[i] = v[i][yCursor];
1104 if (rIF.isComplex()) {
1105 pYImag[i] = vImag[i][yCursor];
1106 pYMag[i] = ::sqrt (v[i][yCursor] * v[i][yCursor] + vImag[i][yCursor] * vImag[i][yCursor]);
1109 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1111 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1113 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1114 std::ostringstream os;
1115 os << "Row " << yCursor;
1116 std::string title("title ");
1118 rPlotFile.addEzsetCommand (title.c_str());
1119 rPlotFile.addEzsetCommand ("xlabel Column");
1120 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1121 rPlotFile.addEzsetCommand ("lxfrac 0");
1122 rPlotFile.addEzsetCommand ("box");
1123 rPlotFile.addEzsetCommand ("grid");
1124 rPlotFile.addEzsetCommand ("curve 1");
1125 rPlotFile.addEzsetCommand ("color 1");
1126 if (rIF.isComplex()) {
1127 rPlotFile.addEzsetCommand ("dash 1");
1128 rPlotFile.addEzsetCommand ("curve 2");
1129 rPlotFile.addEzsetCommand ("color 4");
1130 rPlotFile.addEzsetCommand ("dash 3");
1131 rPlotFile.addEzsetCommand ("curve 3");
1132 rPlotFile.addEzsetCommand ("color 0");
1133 rPlotFile.addEzsetCommand ("solid");
1134 rPlotFile.setCurveSize (4, nx);
1136 rPlotFile.setCurveSize (2, nx);
1137 rPlotFile.addColumn (0, pX);
1138 rPlotFile.addColumn (1, pYReal);
1139 if (rIF.isComplex()) {
1140 rPlotFile.addColumn (2, pYImag);
1141 rPlotFile.addColumn (3, pYMag);
1143 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1144 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1145 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1146 *theApp->getLog() << os.str().c_str() << "\n";
1147 rPlotFile.addDescription (os.str().c_str());
1151 if (rIF.isComplex()) {
1155 if (theApp->getSetModifyNewDocs())
1156 pPlotDoc->Modify(true);
1157 pPlotDoc->UpdateAllViews();
1162 ImageFileView::OnPlotCol (wxCommandEvent& event)
1164 int xCursor, yCursor;
1165 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1166 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1170 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1171 ImageFileArrayConst v = rIF.getArray();
1172 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1176 if (v != NULL && xCursor < nx) {
1177 double* pX = new double [ny];
1178 double* pYReal = new double [ny];
1179 double* pYImag = NULL;
1180 double* pYMag = NULL;
1181 if (rIF.isComplex()) {
1182 pYImag = new double [ny];
1183 pYMag = new double [ny];
1185 for (int i = 0; i < ny; i++) {
1187 pYReal[i] = v[xCursor][i];
1188 if (rIF.isComplex()) {
1189 pYImag[i] = vImag[xCursor][i];
1190 pYMag[i] = ::sqrt (v[xCursor][i] * v[xCursor][i] + vImag[xCursor][i] * vImag[xCursor][i]);
1193 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1195 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1197 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1198 std::ostringstream os;
1199 os << "Column " << xCursor;
1200 std::string title("title ");
1202 rPlotFile.addEzsetCommand (title.c_str());
1203 rPlotFile.addEzsetCommand ("xlabel Row");
1204 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1205 rPlotFile.addEzsetCommand ("lxfrac 0");
1206 rPlotFile.addEzsetCommand ("box");
1207 rPlotFile.addEzsetCommand ("grid");
1208 rPlotFile.addEzsetCommand ("curve 1");
1209 rPlotFile.addEzsetCommand ("color 1");
1210 if (rIF.isComplex()) {
1211 rPlotFile.addEzsetCommand ("dash 1");
1212 rPlotFile.addEzsetCommand ("curve 2");
1213 rPlotFile.addEzsetCommand ("color 4");
1214 rPlotFile.addEzsetCommand ("dash 3");
1215 rPlotFile.addEzsetCommand ("curve 3");
1216 rPlotFile.addEzsetCommand ("color 0");
1217 rPlotFile.addEzsetCommand ("solid");
1218 rPlotFile.setCurveSize (4, ny);
1220 rPlotFile.setCurveSize (2, ny);
1221 rPlotFile.addColumn (0, pX);
1222 rPlotFile.addColumn (1, pYReal);
1223 if (rIF.isComplex()) {
1224 rPlotFile.addColumn (2, pYImag);
1225 rPlotFile.addColumn (3, pYMag);
1227 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1228 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1229 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1230 *theApp->getLog() << os.str().c_str() << "\n";
1231 rPlotFile.addDescription (os.str().c_str());
1235 if (rIF.isComplex()) {
1239 if (theApp->getSetModifyNewDocs())
1240 pPlotDoc->Modify(true);
1241 pPlotDoc->UpdateAllViews();
1247 ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
1249 int xCursor, yCursor;
1250 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1251 wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");
1255 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1256 ImageFileArrayConst v = rIF.getArray();
1257 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1261 if (v != NULL && yCursor < ny) {
1262 fftw_complex* pcIn = new fftw_complex [nx];
1265 for (i = 0; i < nx; i++) {
1266 pcIn[i].re = v[i][yCursor];
1267 if (rIF.isComplex())
1268 pcIn[i].im = vImag[i][yCursor];
1273 fftw_plan plan = fftw_create_plan (nx, FFTW_FORWARD, FFTW_IN_PLACE);
1274 fftw_one (plan, pcIn, NULL);
1275 fftw_destroy_plan (plan);
1277 double* pX = new double [nx];
1278 double* pYReal = new double [nx];
1279 double* pYImag = new double [nx];
1280 double* pYMag = new double [nx];
1281 for (i = 0; i < nx; i++) {
1283 pYReal[i] = pcIn[i].re;
1284 pYImag[i] = pcIn[i].im;
1285 pYMag[i] = ::sqrt (pcIn[i].re * pcIn[i].re + pcIn[i].im * pcIn[i].im);
1287 Fourier::shuffleFourierToNaturalOrder (pYReal, nx);
1288 Fourier::shuffleFourierToNaturalOrder (pYImag, nx);
1289 Fourier::shuffleFourierToNaturalOrder (pYMag, nx);
1291 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1293 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1295 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1296 std::ostringstream os;
1297 os << "Row " << yCursor;
1298 std::string title("title ");
1300 rPlotFile.addEzsetCommand (title.c_str());
1301 rPlotFile.addEzsetCommand ("xlabel Column");
1302 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1303 rPlotFile.addEzsetCommand ("lxfrac 0");
1304 rPlotFile.addEzsetCommand ("curve 1");
1305 rPlotFile.addEzsetCommand ("color 1");
1306 rPlotFile.addEzsetCommand ("dash 1");
1307 rPlotFile.addEzsetCommand ("curve 2");
1308 rPlotFile.addEzsetCommand ("color 4");
1309 rPlotFile.addEzsetCommand ("dash 3");
1310 rPlotFile.addEzsetCommand ("curve 3");
1311 rPlotFile.addEzsetCommand ("color 0");
1312 rPlotFile.addEzsetCommand ("solid");
1313 rPlotFile.addEzsetCommand ("box");
1314 rPlotFile.addEzsetCommand ("grid");
1315 rPlotFile.setCurveSize (4, nx);
1316 rPlotFile.addColumn (0, pX);
1317 rPlotFile.addColumn (1, pYReal);
1318 rPlotFile.addColumn (2, pYImag);
1319 rPlotFile.addColumn (3, pYMag);
1320 for (int iL = 0; iL < rIF.nLabels(); iL++)
1321 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1322 os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1323 *theApp->getLog() << os.str().c_str() << "\n";
1324 rPlotFile.addDescription (os.str().c_str());
1332 if (theApp->getSetModifyNewDocs())
1333 pPlotDoc->Modify(true);
1334 pPlotDoc->UpdateAllViews();
1339 ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
1341 int xCursor, yCursor;
1342 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1343 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1347 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1348 ImageFileArrayConst v = rIF.getArray();
1349 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1353 if (v != NULL && xCursor < nx) {
1354 fftw_complex* pcIn = new fftw_complex [ny];
1355 double *pdTemp = new double [ny];
1358 for (i = 0; i < ny; i++)
1359 pdTemp[i] = v[xCursor][i];
1360 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1361 for (i = 0; i < ny; i++)
1362 pcIn[i].re = pdTemp[i];
1364 for (i = 0; i < ny; i++) {
1365 if (rIF.isComplex())
1366 pdTemp[i] = vImag[xCursor][i];
1370 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1371 for (i = 0; i < ny; i++)
1372 pcIn[i].im = pdTemp[i];
1374 fftw_plan plan = fftw_create_plan (ny, FFTW_BACKWARD, FFTW_IN_PLACE);
1375 fftw_one (plan, pcIn, NULL);
1376 fftw_destroy_plan (plan);
1378 double* pX = new double [ny];
1379 double* pYReal = new double [ny];
1380 double* pYImag = new double [ny];
1381 double* pYMag = new double [ny];
1382 for (i = 0; i < ny; i++) {
1384 pYReal[i] = pcIn[i].re;
1385 pYImag[i] = pcIn[i].im;
1386 pYMag[i] = ::sqrt (pcIn[i].re * pcIn[i].re + pcIn[i].im * pcIn[i].im);
1389 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1391 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1393 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1394 std::ostringstream os;
1395 os << "Column " << xCursor;
1396 std::string title("title ");
1398 rPlotFile.addEzsetCommand (title.c_str());
1399 rPlotFile.addEzsetCommand ("xlabel Column");
1400 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1401 rPlotFile.addEzsetCommand ("lxfrac 0");
1402 rPlotFile.addEzsetCommand ("curve 1");
1403 rPlotFile.addEzsetCommand ("color 1");
1404 rPlotFile.addEzsetCommand ("dash 1");
1405 rPlotFile.addEzsetCommand ("curve 2");
1406 rPlotFile.addEzsetCommand ("color 4");
1407 rPlotFile.addEzsetCommand ("dash 3");
1408 rPlotFile.addEzsetCommand ("curve 3");
1409 rPlotFile.addEzsetCommand ("color 0");
1410 rPlotFile.addEzsetCommand ("solid");
1411 rPlotFile.addEzsetCommand ("box");
1412 rPlotFile.addEzsetCommand ("grid");
1413 rPlotFile.setCurveSize (4, ny);
1414 rPlotFile.addColumn (0, pX);
1415 rPlotFile.addColumn (1, pYReal);
1416 rPlotFile.addColumn (2, pYImag);
1417 rPlotFile.addColumn (3, pYMag);
1418 for (int iL = 0; iL < rIF.nLabels(); iL++)
1419 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1420 os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1421 *theApp->getLog() << os.str().c_str() << "\n";
1422 rPlotFile.addDescription (os.str().c_str());
1431 if (theApp->getSetModifyNewDocs())
1432 pPlotDoc->Modify(true);
1433 pPlotDoc->UpdateAllViews();
1439 ImageFileView::OnCompareCol (wxCommandEvent& event)
1441 int xCursor, yCursor;
1442 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1443 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1447 std::vector<ImageFileDocument*> vecIFDoc;
1448 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1449 if (vecIFDoc.size() == 0) {
1450 wxMessageBox ("No compatible images for Column Comparison", "Error");
1453 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Comparison Image", vecIFDoc, false);
1455 if (dialogGetCompare.ShowModal() == wxID_OK) {
1456 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1457 const ImageFile& rIF = GetDocument()->getImageFile();
1458 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1460 ImageFileArrayConst v1 = rIF.getArray();
1461 ImageFileArrayConst v2 = rCompareIF.getArray();
1465 if (v1 != NULL && xCursor < nx) {
1466 double* pX = new double [ny];
1467 double* pY1 = new double [ny];
1468 double* pY2 = new double [ny];
1469 for (int i = 0; i < ny; i++) {
1471 pY1[i] = v1[xCursor][i];
1472 pY2[i] = v2[xCursor][i];
1474 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1476 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1478 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1479 std::ostringstream os;
1480 os << "Column " << xCursor << " Comparison";
1481 std::string title("title ");
1483 rPlotFile.addEzsetCommand (title.c_str());
1484 rPlotFile.addEzsetCommand ("xlabel Row");
1485 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1486 rPlotFile.addEzsetCommand ("lxfrac 0");
1487 rPlotFile.addEzsetCommand ("curve 1");
1488 rPlotFile.addEzsetCommand ("color 2");
1489 rPlotFile.addEzsetCommand ("curve 2");
1490 rPlotFile.addEzsetCommand ("color 4");
1491 rPlotFile.addEzsetCommand ("dash 5");
1492 rPlotFile.addEzsetCommand ("box");
1493 rPlotFile.addEzsetCommand ("grid");
1494 rPlotFile.setCurveSize (3, ny);
1495 rPlotFile.addColumn (0, pX);
1496 rPlotFile.addColumn (1, pY1);
1497 rPlotFile.addColumn (2, pY2);
1500 for (iL = 0; iL < rIF.nLabels(); iL++) {
1501 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1503 s += rIF.labelGet(iL).getLabelString();
1504 rPlotFile.addDescription (s.c_str());
1506 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1507 std::string s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1509 s += rCompareIF.labelGet(iL).getLabelString();
1510 rPlotFile.addDescription (s.c_str());
1512 os << " Between " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
1513 << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1514 *theApp->getLog() << os.str().c_str() << "\n";
1515 rPlotFile.addDescription (os.str().c_str());
1520 if (theApp->getSetModifyNewDocs())
1521 pPlotDoc->Modify(true);
1522 pPlotDoc->UpdateAllViews();
1528 ImageFileView::OnCompareRow (wxCommandEvent& event)
1530 int xCursor, yCursor;
1531 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1532 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1536 std::vector<ImageFileDocument*> vecIFDoc;
1537 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1539 if (vecIFDoc.size() == 0) {
1540 wxMessageBox ("No compatible images for Row Comparison", "Error");
1544 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Comparison Image", vecIFDoc, false);
1546 if (dialogGetCompare.ShowModal() == wxID_OK) {
1547 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1548 const ImageFile& rIF = GetDocument()->getImageFile();
1549 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1551 ImageFileArrayConst v1 = rIF.getArray();
1552 ImageFileArrayConst v2 = rCompareIF.getArray();
1556 if (v1 != NULL && yCursor < ny) {
1557 double* pX = new double [nx];
1558 double* pY1 = new double [nx];
1559 double* pY2 = new double [nx];
1560 for (int i = 0; i < nx; i++) {
1562 pY1[i] = v1[i][yCursor];
1563 pY2[i] = v2[i][yCursor];
1565 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1567 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1569 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1570 std::ostringstream os;
1571 os << "Row " << yCursor << " Comparison";
1572 std::string title("title ");
1574 rPlotFile.addEzsetCommand (title.c_str());
1575 rPlotFile.addEzsetCommand ("xlabel Column");
1576 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1577 rPlotFile.addEzsetCommand ("lxfrac 0");
1578 rPlotFile.addEzsetCommand ("curve 1");
1579 rPlotFile.addEzsetCommand ("color 2");
1580 rPlotFile.addEzsetCommand ("curve 2");
1581 rPlotFile.addEzsetCommand ("color 4");
1582 rPlotFile.addEzsetCommand ("dash 5");
1583 rPlotFile.addEzsetCommand ("box");
1584 rPlotFile.addEzsetCommand ("grid");
1585 rPlotFile.setCurveSize (3, nx);
1586 rPlotFile.addColumn (0, pX);
1587 rPlotFile.addColumn (1, pY1);
1588 rPlotFile.addColumn (2, pY2);
1590 for (iL = 0; iL < rIF.nLabels(); iL++) {
1591 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1593 s += rIF.labelGet(iL).getLabelString();
1594 rPlotFile.addDescription (s.c_str());
1596 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1597 std::string s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1599 s += rCompareIF.labelGet(iL).getLabelString();
1600 rPlotFile.addDescription (s.c_str());
1602 os << " Between " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
1603 << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1604 *theApp->getLog() << os.str().c_str() << "\n";
1605 rPlotFile.addDescription (os.str().c_str());
1610 if (theApp->getSetModifyNewDocs())
1611 pPlotDoc->Modify(true);
1612 pPlotDoc->UpdateAllViews();
1617 static int NUMBER_HISTOGRAM_BINS = 256;
1620 ImageFileView::OnPlotHistogram (wxCommandEvent& event)
1622 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1623 ImageFileArrayConst v = rIF.getArray();
1627 if (v != NULL && nx > 0 && ny > 0) {
1628 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1630 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1634 double* pX = new double [NUMBER_HISTOGRAM_BINS];
1635 double* pY = new double [NUMBER_HISTOGRAM_BINS];
1637 rIF.getMinMax (dMin, dMax);
1638 double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
1640 for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
1641 pX[i] = dMin + (i + 0.5) * dBinWidth;
1644 for (int ix = 0; ix < nx; ix++)
1645 for (int iy = 0; iy < ny; iy++) {
1646 int iBin = nearest<int> ((v[ix][iy] - dMin) / dBinWidth);
1647 if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
1651 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1652 std::ostringstream os;
1654 std::string title("title ");
1656 rPlotFile.addEzsetCommand (title.c_str());
1657 rPlotFile.addEzsetCommand ("xlabel Pixel Value");
1658 rPlotFile.addEzsetCommand ("ylabel Count");
1659 rPlotFile.addEzsetCommand ("box");
1660 rPlotFile.addEzsetCommand ("grid");
1661 rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
1662 rPlotFile.addColumn (0, pX);
1663 rPlotFile.addColumn (1, pY);
1664 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++) {
1665 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1667 s += rIF.labelGet(iL).getLabelString();
1668 rPlotFile.addDescription (s.c_str());
1670 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1671 *theApp->getLog() << os.str().c_str() << "\n";
1672 rPlotFile.addDescription (os.str().c_str());
1675 if (theApp->getSetModifyNewDocs())
1676 pPlotDoc->Modify(true);
1677 pPlotDoc->UpdateAllViews();
1684 PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1685 : wxScrolledWindow(frame, -1, pos, size, style)
1691 PhantomCanvas::OnDraw (wxDC& dc)
1694 m_pView->OnDraw(& dc);
1700 IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView)
1702 BEGIN_EVENT_TABLE(PhantomView, wxView)
1703 EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomView::OnProperties)
1704 EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomView::OnRasterize)
1705 EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomView::OnProjections)
1708 PhantomView::PhantomView(void)
1709 : wxView(), m_canvas(NULL), m_frame(NULL)
1711 m_iDefaultNDet = 367;
1712 m_iDefaultNView = 320;
1713 m_iDefaultNSample = 2;
1714 m_dDefaultRotation = 1;
1715 m_dDefaultFocalLength = 2;
1716 m_dDefaultFieldOfView = 1;
1717 m_iDefaultGeometry = Scanner::GEOMETRY_PARALLEL;
1718 m_iDefaultTrace = Trace::TRACE_NONE;
1720 m_iDefaultRasterNX = 256;
1721 m_iDefaultRasterNY = 256;
1722 m_iDefaultRasterNSamples = 2;
1725 PhantomView::~PhantomView(void)
1730 PhantomView::OnProperties (wxCommandEvent& event)
1732 const int idPhantom = GetDocument()->getPhantomID();
1733 const wxString& namePhantom = GetDocument()->getPhantomName();
1734 std::ostringstream os;
1735 os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n";
1736 const Phantom& rPhantom = GetDocument()->getPhantom();
1737 rPhantom.printDefinitions (os);
1739 rPhantom.print (os);
1741 *theApp->getLog() << os.str().c_str() << "\n";
1742 wxMessageBox (os.str().c_str(), "Phantom Properties");
1747 PhantomView::OnProjections (wxCommandEvent& event)
1749 DialogGetProjectionParameters dialogProjection (getFrameForChild(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView, m_iDefaultGeometry, m_iDefaultTrace);
1750 int retVal = dialogProjection.ShowModal();
1751 if (retVal == wxID_OK) {
1752 m_iDefaultNDet = dialogProjection.getNDet();
1753 m_iDefaultNView = dialogProjection.getNView();
1754 m_iDefaultNSample = dialogProjection.getNSamples();
1755 m_iDefaultTrace = dialogProjection.getTrace();
1756 m_dDefaultRotation = dialogProjection.getRotAngle();
1757 m_dDefaultFocalLength = dialogProjection.getFocalLengthRatio();
1758 m_dDefaultFieldOfView = dialogProjection.getFieldOfViewRatio();
1759 wxString sGeometry = dialogProjection.getGeometry();
1760 m_iDefaultGeometry = Scanner::convertGeometryNameToID (sGeometry.c_str());
1762 if (m_iDefaultNDet > 0 && m_iDefaultNView > 0 && sGeometry != "") {
1763 const Phantom& rPhantom = GetDocument()->getPhantom();
1764 ProjectionFileDocument* pProjectionDoc = dynamic_cast<ProjectionFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT));
1765 if (! pProjectionDoc) {
1766 sys_error (ERR_SEVERE, "Unable to create projection document");
1769 Projections& rProj = pProjectionDoc->getProjections();
1770 Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView);
1771 if (theScanner.fail()) {
1772 *theApp->getLog() << "Failed making scanner: " << theScanner.failMessage().c_str() << "\n";
1775 rProj.initFromScanner (theScanner);
1776 m_dDefaultRotation /= PI; // convert back to PI units
1779 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
1780 ProjectionsDialog dialogProjections (theScanner, rProj, rPhantom, m_iDefaultTrace, dynamic_cast<wxWindow*>(getFrameForChild()));
1781 for (int iView = 0; iView < rProj.nView(); iView++) {
1784 if (dialogProjections.isCancelled() || ! dialogProjections.projectView (iView)) {
1785 pProjectionDoc->DeleteAllViews();
1790 while (dialogProjections.isPaused()) {
1796 wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT);
1797 for (int i = 0; i < rProj.nView(); i++) {
1798 theScanner.collectProjections (rProj, rPhantom, i, 1, true, m_iDefaultTrace);
1799 if (! dlgProgress.Update (i+1)) {
1800 pProjectionDoc->DeleteAllViews();
1806 std::ostringstream os;
1807 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();
1808 rProj.setCalcTime (timer.timerEnd());
1809 rProj.setRemark (os.str());
1810 *theApp->getLog() << os.str().c_str() << "\n";
1814 ProjectionFileView* projView = dynamic_cast<ProjectionFileView*>(pProjectionDoc->GetFirstView());
1816 projView->getFrame()->SetFocus();
1817 projView->OnUpdate (projView, NULL);
1819 if (wxView* pView = pProjectionDoc->GetFirstView()) {
1820 if (wxFrame* pFrame = pView->GetFrame()) {
1824 theApp->getDocManager()->ActivateView (pView, true, false);
1827 if (theApp->getSetModifyNewDocs())
1828 pProjectionDoc->Modify(true);
1829 pProjectionDoc->UpdateAllViews(this);
1836 PhantomView::OnRasterize (wxCommandEvent& event)
1838 DialogGetRasterParameters dialogRaster (getFrameForChild(), m_iDefaultRasterNX, m_iDefaultRasterNY, m_iDefaultRasterNSamples);
1839 int retVal = dialogRaster.ShowModal();
1840 if (retVal == wxID_OK) {
1841 m_iDefaultRasterNX = dialogRaster.getXSize();
1842 m_iDefaultRasterNY = dialogRaster.getYSize();
1843 m_iDefaultRasterNSamples = dialogRaster.getNSamples();
1844 if (m_iDefaultRasterNSamples < 1)
1845 m_iDefaultRasterNSamples = 1;
1846 if (m_iDefaultRasterNX > 0 && m_iDefaultRasterNY > 0) {
1847 const Phantom& rPhantom = GetDocument()->getPhantom();
1848 ImageFileDocument* pRasterDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
1850 sys_error (ERR_SEVERE, "Unable to create image file");
1853 ImageFile& imageFile = pRasterDoc->getImageFile();
1855 imageFile.setArraySize (m_iDefaultRasterNX, m_iDefaultRasterNX);
1856 wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, getFrameForChild(), wxPD_CAN_ABORT);
1858 for (unsigned int i = 0; i < imageFile.nx(); i++) {
1859 rPhantom.convertToImagefile (imageFile, m_iDefaultRasterNSamples, Trace::TRACE_NONE, i, 1, true);
1860 if (! dlgProgress.Update(i+1)) {
1861 pRasterDoc->DeleteAllViews();
1865 if (theApp->getSetModifyNewDocs())
1866 pRasterDoc->Modify(true);
1867 pRasterDoc->UpdateAllViews(this);
1868 std::ostringstream os;
1869 os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << m_iDefaultRasterNX << ", YSize="
1870 << m_iDefaultRasterNY << ", nSamples=" << m_iDefaultRasterNSamples;
1871 *theApp->getLog() << os.str().c_str() << "\n";
1872 imageFile.labelAdd (os.str().c_str(), timer.timerEnd());
1873 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pRasterDoc->GetFirstView());
1875 rasterView->getFrame()->SetFocus();
1876 rasterView->OnUpdate (rasterView, NULL);
1885 PhantomView::CreateCanvas (wxView *view, wxFrame *parent)
1887 PhantomCanvas* pCanvas;
1889 parent->GetClientSize(&width, &height);
1891 pCanvas = new PhantomCanvas (dynamic_cast<PhantomView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1893 pCanvas->SetBackgroundColour(*wxWHITE);
1900 PhantomView::CreateChildFrame(wxDocument *doc, wxView *view)
1903 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1905 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1907 theApp->setIconForFrame (subframe);
1909 wxMenu *file_menu = new wxMenu;
1911 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
1912 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
1913 file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
1914 file_menu->Append(wxID_SAVEAS, "Save &As...");
1915 file_menu->Append(wxID_CLOSE, "&Close");
1917 file_menu->AppendSeparator();
1918 file_menu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties");
1920 file_menu->AppendSeparator();
1921 file_menu->Append(wxID_PRINT, "&Print...");
1922 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1923 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1925 wxMenu *process_menu = new wxMenu;
1926 process_menu->Append(PHMMENU_PROCESS_RASTERIZE, "&Rasterize...\tCtrl-R");
1927 process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, "&Projections...\tCtrl-J");
1929 wxMenu *help_menu = new wxMenu;
1930 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
1931 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
1932 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1934 wxMenuBar *menu_bar = new wxMenuBar;
1936 menu_bar->Append(file_menu, "&File");
1937 menu_bar->Append(process_menu, "&Process");
1938 menu_bar->Append(help_menu, "&Help");
1940 subframe->SetMenuBar(menu_bar);
1941 subframe->Centre(wxBOTH);
1943 wxAcceleratorEntry accelEntries[8];
1944 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
1945 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
1946 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
1947 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
1948 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
1949 accelEntries[5].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
1950 accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('J'), PHMMENU_PROCESS_PROJECTIONS);
1951 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('R'), PHMMENU_PROCESS_RASTERIZE);
1952 wxAcceleratorTable accelTable (8, accelEntries);
1953 subframe->SetAcceleratorTable (accelTable);
1960 PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1962 m_frame = CreateChildFrame(doc, this);
1966 m_frame->GetClientSize(&width, &height);
1967 m_frame->SetTitle("PhantomView");
1968 m_canvas = CreateCanvas (this, m_frame);
1971 int x, y; // X requires a forced resize
1972 m_frame->GetSize(&x, &y);
1973 m_frame->SetSize(-1, -1, x, y);
1976 m_frame->Show(true);
1983 PhantomView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1986 m_canvas->Refresh();
1990 PhantomView::OnClose (bool deleteWindow)
1992 if (!GetDocument()->Close())
1996 //m_canvas->m_pView = NULL;
1998 wxString s(wxTheApp->GetAppName());
2000 m_frame->SetTitle(s);
2012 PhantomView::OnDraw (wxDC* dc)
2015 m_canvas->GetClientSize (&xsize, &ysize);
2016 SGPDriver driver (dc, xsize, ysize);
2018 const Phantom& rPhantom = GetDocument()->getPhantom();
2019 sgp.setColor (C_RED);
2020 rPhantom.show (sgp);
2025 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2026 : wxScrolledWindow(frame, -1, pos, size, style)
2032 ProjectionFileCanvas::OnDraw(wxDC& dc)
2035 m_pView->OnDraw(& dc);
2039 ProjectionFileCanvas::GetBestSize () const
2043 Projections& rProj = m_pView->GetDocument()->getProjections();
2044 best.Set (rProj.nDet(), rProj.nView());
2051 // ProjectionFileView
2053 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
2055 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
2056 EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
2057 EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
2058 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
2059 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
2062 ProjectionFileView::ProjectionFileView(void)
2063 : wxView(), m_canvas(NULL), m_frame(NULL)
2067 m_iDefaultFilter = SignalFilter::FILTER_ABS_BANDLIMIT;
2068 m_dDefaultFilterParam = 1.;
2070 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_RFFTW;
2071 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER;
2073 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_CONVOLUTION;
2074 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT;
2076 m_iDefaultZeropad = 1;
2077 m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF3;
2078 m_iDefaultInterpolation = Backprojector::INTERP_LINEAR;
2079 m_iDefaultInterpParam = 1;
2080 m_iDefaultTrace = Trace::TRACE_NONE;
2082 m_iDefaultPolarNX = 256;
2083 m_iDefaultPolarNY = 256;
2084 m_iDefaultPolarInterpolation = Projections::POLAR_INTERP_BILINEAR;
2085 m_iDefaultPolarZeropad = 1;
2088 ProjectionFileView::~ProjectionFileView(void)
2093 ProjectionFileView::OnProperties (wxCommandEvent& event)
2095 const Projections& rProj = GetDocument()->getProjections();
2096 std::ostringstream os;
2097 rProj.printScanInfo(os);
2098 *theApp->getLog() << os.str().c_str();
2099 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Projection File Properties", wxOK | wxICON_INFORMATION);
2100 dialogMsg.ShowModal();
2105 ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
2107 Projections& rProj = GetDocument()->getProjections();
2108 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
2109 m_iDefaultPolarInterpolation, -1);
2110 if (dialogPolar.ShowModal() == wxID_OK) {
2111 wxString strInterpolation (dialogPolar.getInterpolationName());
2112 m_iDefaultPolarNX = dialogPolar.getXSize();
2113 m_iDefaultPolarNY = dialogPolar.getYSize();
2114 ImageFileDocument* pPolarDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2115 ImageFile& rIF = pPolarDoc->getImageFile();
2117 sys_error (ERR_SEVERE, "Unable to create image file");
2120 rIF.setArraySize (m_iDefaultPolarNX, m_iDefaultPolarNY);
2121 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
2122 rProj.convertPolar (rIF, m_iDefaultPolarInterpolation);
2123 rIF.labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2124 std::ostringstream os;
2125 os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to polar image: xSize="
2126 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2127 << strInterpolation.c_str();
2128 *theApp->getLog() << os.str().c_str() << "\n";
2129 rIF.labelAdd (os.str().c_str());
2130 if (theApp->getSetModifyNewDocs())
2131 pPolarDoc->Modify(true);
2132 pPolarDoc->UpdateAllViews();
2133 pPolarDoc->GetFirstView()->OnUpdate (this, NULL);
2138 ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
2140 Projections& rProj = GetDocument()->getProjections();
2141 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert to FFT Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
2142 m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad);
2143 if (dialogPolar.ShowModal() == wxID_OK) {
2144 wxString strInterpolation (dialogPolar.getInterpolationName());
2145 m_iDefaultPolarNX = dialogPolar.getXSize();
2146 m_iDefaultPolarNY = dialogPolar.getYSize();
2147 m_iDefaultPolarZeropad = dialogPolar.getZeropad();
2148 ImageFileDocument* pPolarDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2149 ImageFile& rIF = pPolarDoc->getImageFile();
2151 sys_error (ERR_SEVERE, "Unable to create image file");
2154 rIF.setArraySize (m_iDefaultPolarNX, m_iDefaultPolarNY);
2155 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
2156 rProj.convertFFTPolar (rIF, m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad);
2157 rIF.labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2158 std::ostringstream os;
2159 os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to FFT polar image: xSize="
2160 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2161 << strInterpolation.c_str() << ", zeropad=" << m_iDefaultPolarZeropad;
2162 *theApp->getLog() << os.str().c_str() << "\n";
2163 rIF.labelAdd (os.str().c_str());
2164 if (theApp->getSetModifyNewDocs())
2165 pPolarDoc->Modify(true);
2166 pPolarDoc->UpdateAllViews();
2167 pPolarDoc->GetFirstView()->OnUpdate (this, NULL);
2171 ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
2173 wxMessageBox ("Fourier Reconstruction is not yet supported", "Unimplemented function");
2177 ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
2179 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);
2181 int retVal = dialogReconstruction.ShowModal();
2182 if (retVal == wxID_OK) {
2183 m_iDefaultNX = dialogReconstruction.getXSize();
2184 m_iDefaultNY = dialogReconstruction.getYSize();
2185 wxString optFilterName = dialogReconstruction.getFilterName();
2186 m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.c_str());
2187 m_dDefaultFilterParam = dialogReconstruction.getFilterParam();
2188 wxString optFilterMethodName = dialogReconstruction.getFilterMethodName();
2189 m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.c_str());
2190 m_iDefaultZeropad = dialogReconstruction.getZeropad();
2191 wxString optFilterGenerationName = dialogReconstruction.getFilterGenerationName();
2192 m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.c_str());
2193 wxString optInterpName = dialogReconstruction.getInterpName();
2194 m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.c_str());
2195 m_iDefaultInterpParam = dialogReconstruction.getInterpParam();
2196 wxString optBackprojectName = dialogReconstruction.getBackprojectName();
2197 m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str());
2198 m_iDefaultTrace = dialogReconstruction.getTrace();
2199 if (m_iDefaultNX > 0 && m_iDefaultNY > 0) {
2200 ImageFileDocument* pReconDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2202 sys_error (ERR_SEVERE, "Unable to create image file");
2205 ImageFile& imageFile = pReconDoc->getImageFile();
2206 const Projections& rProj = GetDocument()->getProjections();
2207 imageFile.setArraySize (m_iDefaultNX, m_iDefaultNY);
2209 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);
2212 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
2213 ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstruct, rProj, imageFile, m_iDefaultTrace, getFrameForChild());
2214 for (int iView = 0; iView < rProj.nView(); iView++) {
2217 if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView)) {
2218 delete pDlgReconstruct;
2219 delete pReconstruct;
2220 pReconDoc->DeleteAllViews();
2225 while (pDlgReconstruct->isPaused()) {
2230 delete pDlgReconstruct;
2232 wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT);
2233 for (int i = 0; i < rProj.nView(); i++) {
2234 pReconstruct->reconstructView (i, 1);
2235 if (! dlgProgress.Update(i + 1)) {
2236 delete pReconstruct;
2237 pReconDoc->DeleteAllViews();
2242 delete pReconstruct;
2243 if (theApp->getSetModifyNewDocs())
2244 pReconDoc->Modify(true);
2245 pReconDoc->UpdateAllViews(this);
2246 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pReconDoc->GetFirstView());
2248 rasterView->getFrame()->SetFocus();
2249 rasterView->OnUpdate (rasterView, NULL);
2251 std::ostringstream os;
2252 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();
2253 *theApp->getLog() << os.str().c_str() << "\n";
2254 imageFile.labelAdd (rProj.getLabel());
2255 imageFile.labelAdd (os.str().c_str(), timerRecon.timerEnd());
2261 ProjectionFileCanvas*
2262 ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent)
2264 ProjectionFileCanvas* pCanvas;
2266 parent->GetClientSize(&width, &height);
2268 pCanvas = new ProjectionFileCanvas (dynamic_cast<ProjectionFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
2270 pCanvas->SetScrollbars(20, 20, 50, 50);
2271 pCanvas->SetBackgroundColour(*wxWHITE);
2278 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
2281 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
2283 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
2285 theApp->setIconForFrame (subframe);
2287 wxMenu *file_menu = new wxMenu;
2289 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
2290 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
2291 file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
2292 file_menu->Append(wxID_SAVE, "&Save\tCtrl-S");
2293 file_menu->Append(wxID_SAVEAS, "Save &As...");
2294 file_menu->Append(wxID_CLOSE, "&Close\tCtrl-W");
2296 file_menu->AppendSeparator();
2297 file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
2299 file_menu->AppendSeparator();
2300 file_menu->Append(wxID_PRINT, "&Print...");
2301 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
2302 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
2304 wxMenu *convert_menu = new wxMenu;
2305 convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L");
2306 convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-I");
2308 wxMenu *reconstruct_menu = new wxMenu;
2309 reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R");
2310 reconstruct_menu->Append (PJMENU_RECONSTRUCT_FOURIER, "&Fourier...\tCtrl-E");
2312 wxMenu *help_menu = new wxMenu;
2313 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
2314 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
2315 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
2317 wxMenuBar *menu_bar = new wxMenuBar;
2319 menu_bar->Append (file_menu, "&File");
2320 menu_bar->Append (convert_menu, "&Convert");
2321 menu_bar->Append (reconstruct_menu, "&Reconstruct");
2322 menu_bar->Append (help_menu, "&Help");
2324 subframe->SetMenuBar(menu_bar);
2325 subframe->Centre(wxBOTH);
2327 wxAcceleratorEntry accelEntries[11];
2328 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
2329 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
2330 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
2331 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
2332 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
2333 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
2334 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
2335 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
2336 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_CONVERT_FFT_POLAR);
2337 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
2338 accelEntries[10].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
2339 wxAcceleratorTable accelTable (11, accelEntries);
2340 subframe->SetAcceleratorTable (accelTable);
2347 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
2349 m_frame = CreateChildFrame(doc, this);
2353 m_frame->GetClientSize(&width, &height);
2354 m_frame->SetTitle("ProjectionFileView");
2355 m_canvas = CreateCanvas(this, m_frame);
2358 int x, y; // X requires a forced resize
2359 m_frame->GetSize(&x, &y);
2360 m_frame->SetSize(-1, -1, x, y);
2363 m_frame->Show(true);
2370 ProjectionFileView::OnDraw (wxDC* dc)
2372 wxSize clientSize = m_frame->GetClientSize();
2373 wxSize bestSize = m_canvas->GetBestSize();
2375 if (clientSize.x > bestSize.x || clientSize.y > bestSize.y)
2376 m_frame->SetClientSize (bestSize);
2379 dc->DrawBitmap (m_bitmap, 0, 0, false);
2384 ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2386 const Projections& rProj = GetDocument()->getProjections();
2387 const int nDet = rProj.nDet();
2388 const int nView = rProj.nView();
2389 if (nDet != 0 && nView != 0) {
2390 const DetectorArray& detarray = rProj.getDetectorArray(0);
2391 const DetectorValue* detval = detarray.detValues();
2392 double min = detval[0];
2393 double max = detval[0];
2394 for (int iy = 0; iy < nView; iy++) {
2395 const DetectorArray& detarray = rProj.getDetectorArray(iy);
2396 const DetectorValue* detval = detarray.detValues();
2397 for (int ix = 0; ix < nDet; ix++) {
2398 if (min > detval[ix])
2400 else if (max < detval[ix])
2405 unsigned char* imageData = new unsigned char [nDet * nView * 3];
2406 double scale = (max - min) / 255;
2407 for (int iy2 = 0; iy2 < nView; iy2++) {
2408 const DetectorArray& detarray = rProj.getDetectorArray (iy2);
2409 const DetectorValue* detval = detarray.detValues();
2410 for (int ix = 0; ix < nDet; ix++) {
2411 int intensity = static_cast<int>(((detval[ix] - min) / scale) + 0.5);
2412 intensity = clamp(intensity, 0, 255);
2413 int baseAddr = (iy2 * nDet + ix) * 3;
2414 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
2417 wxImage image (nDet, nView, imageData, true);
2418 m_bitmap = image.ConvertToBitmap();
2422 xSize = clamp (xSize, 0, 800);
2423 ySize = clamp (ySize, 0, 800);
2424 m_frame->SetClientSize (xSize, ySize);
2425 m_canvas->SetScrollbars (20, 20, nDet/20, nView/20);
2429 m_canvas->Refresh();
2433 ProjectionFileView::OnClose (bool deleteWindow)
2435 if (!GetDocument()->Close())
2439 // m_canvas->m_pView = NULL;
2441 wxString s(wxTheApp->GetAppName());
2443 m_frame->SetTitle(s);
2458 PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2459 : wxScrolledWindow(frame, -1, pos, size, style)
2465 PlotFileCanvas::OnDraw(wxDC& dc)
2468 m_pView->OnDraw(& dc);
2474 IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
2476 BEGIN_EVENT_TABLE(PlotFileView, wxView)
2477 EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
2478 EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax)
2479 EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto)
2480 EVT_MENU(PLOTMENU_VIEW_SCALE_FULL, PlotFileView::OnScaleFull)
2483 PlotFileView::PlotFileView(void)
2484 : wxView(), m_canvas(NULL), m_frame(NULL), m_pEZPlot(NULL)
2486 m_bMinSpecified = false;
2487 m_bMaxSpecified = false;
2490 PlotFileView::~PlotFileView(void)
2497 PlotFileView::OnProperties (wxCommandEvent& event)
2499 const PlotFile& rPlot = GetDocument()->getPlotFile();
2500 std::ostringstream os;
2501 os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";
2502 rPlot.printHeadersBrief (os);
2503 *theApp->getLog() << os.str().c_str();
2504 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
2505 dialogMsg.ShowModal();
2510 PlotFileView::OnScaleAuto (wxCommandEvent& event)
2512 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2513 double min, max, mean, mode, median, stddev;
2514 rPlotFile.statistics (1, min, max, mean, mode, median, stddev);
2515 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
2516 int iRetVal = dialogAutoScale.ShowModal();
2517 if (iRetVal == wxID_OK) {
2518 m_bMinSpecified = true;
2519 m_bMaxSpecified = true;
2521 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
2524 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
2525 OnUpdate (this, NULL);
2531 PlotFileView::OnScaleMinMax (wxCommandEvent& event)
2533 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2537 if (! m_bMinSpecified || ! m_bMaxSpecified) {
2538 if (! rPlotFile.getMinMax (1, min, max)) {
2539 *theApp->getLog() << "Error: unable to find Min/Max\n";
2544 if (m_bMinSpecified)
2546 if (m_bMaxSpecified)
2549 DialogGetMinMax dialogMinMax (getFrameForChild(), "Set Y-axis Minimum & Maximum", min, max);
2550 int retVal = dialogMinMax.ShowModal();
2551 if (retVal == wxID_OK) {
2552 m_bMinSpecified = true;
2553 m_bMaxSpecified = true;
2554 m_dMinPixel = dialogMinMax.getMinimum();
2555 m_dMaxPixel = dialogMinMax.getMaximum();
2556 OnUpdate (this, NULL);
2561 PlotFileView::OnScaleFull (wxCommandEvent& event)
2563 if (m_bMinSpecified || m_bMaxSpecified) {
2564 m_bMinSpecified = false;
2565 m_bMaxSpecified = false;
2566 OnUpdate (this, NULL);
2572 PlotFileView::CreateCanvas (wxView *view, wxFrame *parent)
2574 PlotFileCanvas* pCanvas;
2576 parent->GetClientSize(&width, &height);
2578 pCanvas = new PlotFileCanvas (dynamic_cast<PlotFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
2580 pCanvas->SetBackgroundColour(*wxWHITE);
2587 PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
2590 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
2592 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
2594 theApp->setIconForFrame (subframe);
2596 wxMenu *file_menu = new wxMenu;
2598 file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
2599 file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
2600 file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
2601 file_menu->Append(wxID_SAVE, "&Save\tCtrl-S");
2602 file_menu->Append(wxID_SAVEAS, "Save &As...");
2603 file_menu->Append(wxID_CLOSE, "&Close\tCtrl-W");
2605 file_menu->AppendSeparator();
2606 file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
2608 file_menu->AppendSeparator();
2609 file_menu->Append(wxID_PRINT, "&Print...");
2610 file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
2611 file_menu->Append(wxID_PREVIEW, "Print Pre&view");
2613 wxMenu *view_menu = new wxMenu;
2614 view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...\tCtrl-E");
2615 view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...\tCtrl-A");
2616 view_menu->Append(PLOTMENU_VIEW_SCALE_FULL, "Display &Full Scale\tCtrl-U");
2618 wxMenu *help_menu = new wxMenu;
2619 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
2620 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
2621 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
2623 wxMenuBar *menu_bar = new wxMenuBar;
2625 menu_bar->Append(file_menu, "&File");
2626 menu_bar->Append(view_menu, "&View");
2627 menu_bar->Append(help_menu, "&Help");
2629 subframe->SetMenuBar(menu_bar);
2630 subframe->Centre(wxBOTH);
2632 wxAcceleratorEntry accelEntries[10];
2633 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
2634 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
2635 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
2636 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
2637 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
2638 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
2639 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
2640 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('E'), PLOTMENU_VIEW_SCALE_MINMAX);
2641 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('A'), PLOTMENU_VIEW_SCALE_AUTO);
2642 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('U'), PLOTMENU_VIEW_SCALE_FULL);
2643 wxAcceleratorTable accelTable (10, accelEntries);
2644 subframe->SetAcceleratorTable (accelTable);
2651 PlotFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
2653 m_frame = CreateChildFrame(doc, this);
2656 m_bMinSpecified = false;
2657 m_bMaxSpecified = false;
2658 m_dAutoScaleFactor = 1.;
2661 m_frame->GetClientSize(&width, &height);
2662 m_frame->SetTitle ("Plot File");
2663 m_canvas = CreateCanvas (this, m_frame);
2666 int x, y; // X requires a forced resize
2667 m_frame->GetSize(&x, &y);
2668 m_frame->SetSize(-1, -1, x, y);
2671 m_frame->Show(true);
2678 PlotFileView::OnDraw (wxDC* dc)
2680 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2681 const int iNColumns = rPlotFile.getNumColumns();
2682 const int iNRecords = rPlotFile.getNumRecords();
2684 if (iNColumns > 0 && iNRecords > 0) {
2686 m_canvas->GetClientSize (&xsize, &ysize);
2687 SGPDriver driver (dc, xsize, ysize);
2690 m_pEZPlot->plot (&sgp);
2696 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2698 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2699 const int iNColumns = rPlotFile.getNumColumns();
2700 const int iNRecords = rPlotFile.getNumRecords();
2702 if (iNColumns > 0 && iNRecords > 0) {
2705 m_pEZPlot = new EZPlot;
2707 for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)
2708 m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));
2710 if (m_bMinSpecified) {
2711 std::ostringstream os;
2712 os << "ymin " << m_dMinPixel;
2713 m_pEZPlot->ezset (os.str());
2716 if (m_bMaxSpecified) {
2717 std::ostringstream os;
2718 os << "ymax " << m_dMaxPixel;
2719 m_pEZPlot->ezset (os.str());
2722 m_pEZPlot->ezset("box");
2723 m_pEZPlot->ezset("grid");
2725 double* pdXaxis = new double [iNRecords];
2726 rPlotFile.getColumn (0, pdXaxis);
2728 double* pdY = new double [iNRecords];
2729 for (int iCol = 1; iCol < iNColumns; iCol++) {
2730 rPlotFile.getColumn (iCol, pdY);
2731 m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords);
2739 m_canvas->Refresh();
2743 PlotFileView::OnClose (bool deleteWindow)
2745 if (!GetDocument()->Close())
2749 // m_canvas->m_pView = NULL;
2751 wxString s(wxTheApp->GetAppName());
2753 m_frame->SetTitle(s);