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-2001 Kevin Rosenberg
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 #include "wx/wxprec.h"
33 #if !wxUSE_DOC_VIEW_ARCHITECTURE
34 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
38 #include "wx/progdlg.h"
39 #include "wx/clipbrd.h"
46 #include "dlgprojections.h"
47 #include "dlgreconstruct.h"
48 #include "backprojectors.h"
49 #include "reconstruct.h"
51 #include "threadproj.h"
52 #include "threadrecon.h"
53 #include "threadraster.h"
55 #if defined(MSVC) || HAVE_SSTREAM
58 #include <sstream_subst>
61 // Used to reduce calls to progress bar update function
62 const short int ITER_PER_UPDATE = 10;
66 BEGIN_EVENT_TABLE(ImageFileCanvas, wxScrolledWindow)
67 EVT_MOUSE_EVENTS(ImageFileCanvas::OnMouseEvent)
68 EVT_CHAR(ImageFileCanvas::OnChar)
72 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
73 : wxScrolledWindow(frame, -1, pos, size, style), m_pView(v), m_xCursor(-1), m_yCursor(-1)
77 ImageFileCanvas::~ImageFileCanvas()
81 ImageFileCanvas::OnDraw(wxDC& dc)
84 m_pView->OnDraw(& dc);
88 ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y)
90 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
95 dc.SetLogicalFunction (wxINVERT);
96 dc.SetPen (*wxGREEN_PEN);
97 dc.DrawLine (0, yPt, nx, yPt);
98 dc.DrawLine (x, 0, x, ny);
99 dc.SetLogicalFunction (wxCOPY);
103 ImageFileCanvas::GetCurrentCursor (int& x, int& y)
108 if (m_xCursor >= 0 && m_yCursor >= 0)
115 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
124 wxPoint pt(event.GetLogicalPosition(dc));
126 const ImageFileDocument* pIFDoc = m_pView->GetDocument();
129 const ImageFile& rIF = pIFDoc->getImageFile();
130 ImageFileArrayConst v = rIF.getArray();
133 const int yPt = ny - 1 - pt.y;
134 if (event.RightIsDown()) {
135 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
137 os << _T("Image value (") << pt.x << _T(",") << yPt << _T(") = ")
139 if (rIF.isComplex()) {
140 double dImag = rIF.getImaginaryArray()[pt.x][yPt];
142 os << _T(" - ") << -dImag;
144 os << _T(" + ") << dImag;
148 *theApp->getLog() << os;
150 *theApp->getLog() << _T("Mouse out of image range (") << pt.x << _T(",") << yPt << _T(")\n");
152 else if (event.LeftIsDown() || event.LeftUp() || event.RightUp()) {
153 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
154 if (m_xCursor >= 0 && m_yCursor >= 0) {
155 DrawRubberBandCursor (dc, m_xCursor, m_yCursor);
157 DrawRubberBandCursor (dc, pt.x, yPt);
160 wxMenu* pMenu = m_pView->getMenuAnalyze();
161 if (pMenu && ! pMenu->IsEnabled(IFMENU_PLOT_ROW)) {
162 pMenu->Enable (IFMENU_PLOT_ROW, true);
163 pMenu->Enable (IFMENU_PLOT_COL, true);
164 pMenu->Enable (IFMENU_COMPARE_ROW, true);
165 pMenu->Enable (IFMENU_COMPARE_COL, true);
166 pMenu->Enable (IFMENU_PLOT_FFT_ROW, true);
167 pMenu->Enable (IFMENU_PLOT_FFT_COL, true);
170 *theApp->getLog() << _T("Mouse out of image range (") << pt.x << _T(",") << yPt << _T(")\n");
172 if (event.LeftUp()) {
174 os << _T("Selected column ") << pt.x << _T(" , row ") << yPt << _T("\n");
175 *theApp->getLog() << os;
180 ImageFileCanvas::OnChar (wxKeyEvent& event)
182 if (event.GetKeyCode() == WXK_ESCAPE) {
186 m_pView->OnUpdate (NULL);
192 ImageFileCanvas::GetBestSize() const
194 const int iMinX = 50;
195 const int iMinY = 20;
196 wxSize bestSize (iMinX,iMinY);
199 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
200 bestSize.Set (rIF.nx(), rIF.ny());
203 if (bestSize.x > 800)
205 if (bestSize.y > 800)
208 if (bestSize.y < iMinY)
210 if (bestSize.x < iMinX)
219 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
221 BEGIN_EVENT_TABLE(ImageFileView, wxView)
222 EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
223 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
224 EVT_MENU(IFMENU_EDIT_COPY, ImageFileView::OnEditCopy)
225 EVT_MENU(IFMENU_EDIT_CUT, ImageFileView::OnEditCut)
226 EVT_MENU(IFMENU_EDIT_PASTE, ImageFileView::OnEditPaste)
227 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
228 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
229 EVT_MENU(IFMENU_VIEW_SCALE_FULL, ImageFileView::OnScaleFull)
230 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)
231 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)
232 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)
233 EVT_MENU(IFMENU_FILTER_INVERTVALUES, ImageFileView::OnInvertValues)
234 EVT_MENU(IFMENU_FILTER_SQUARE, ImageFileView::OnSquare)
235 EVT_MENU(IFMENU_FILTER_SQRT, ImageFileView::OnSquareRoot)
236 EVT_MENU(IFMENU_FILTER_LOG, ImageFileView::OnLog)
237 EVT_MENU(IFMENU_FILTER_EXP, ImageFileView::OnExp)
238 EVT_MENU(IFMENU_FILTER_FOURIER, ImageFileView::OnFourier)
239 EVT_MENU(IFMENU_FILTER_INVERSE_FOURIER, ImageFileView::OnInverseFourier)
240 EVT_MENU(IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)
241 EVT_MENU(IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)
242 EVT_MENU(IFMENU_IMAGE_ADD, ImageFileView::OnAdd)
243 EVT_MENU(IFMENU_IMAGE_SUBTRACT, ImageFileView::OnSubtract)
244 EVT_MENU(IFMENU_IMAGE_MULTIPLY, ImageFileView::OnMultiply)
245 EVT_MENU(IFMENU_IMAGE_DIVIDE, ImageFileView::OnDivide)
246 EVT_MENU(IFMENU_IMAGE_SCALESIZE, ImageFileView::OnScaleSize)
248 EVT_MENU(IFMENU_IMAGE_CONVERT3D, ImageFileView::OnConvert3d)
251 EVT_MENU(IFMENU_FILTER_FFT, ImageFileView::OnFFT)
252 EVT_MENU(IFMENU_FILTER_IFFT, ImageFileView::OnIFFT)
253 EVT_MENU(IFMENU_FILTER_FFT_ROWS, ImageFileView::OnFFTRows)
254 EVT_MENU(IFMENU_FILTER_IFFT_ROWS, ImageFileView::OnIFFTRows)
255 EVT_MENU(IFMENU_FILTER_FFT_COLS, ImageFileView::OnFFTCols)
256 EVT_MENU(IFMENU_FILTER_IFFT_COLS, ImageFileView::OnIFFTCols)
258 EVT_MENU(IFMENU_FILTER_MAGNITUDE, ImageFileView::OnMagnitude)
259 EVT_MENU(IFMENU_FILTER_PHASE, ImageFileView::OnPhase)
260 EVT_MENU(IFMENU_FILTER_REAL, ImageFileView::OnReal)
261 EVT_MENU(IFMENU_FILTER_IMAGINARY, ImageFileView::OnImaginary)
262 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)
263 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)
265 EVT_MENU(IFMENU_PLOT_FFT_ROW, ImageFileView::OnPlotFFTRow)
266 EVT_MENU(IFMENU_PLOT_FFT_COL, ImageFileView::OnPlotFFTCol)
268 EVT_MENU(IFMENU_PLOT_HISTOGRAM, ImageFileView::OnPlotHistogram)
271 ImageFileView::ImageFileView()
272 : wxView(), m_pBitmap(0), m_pFrame(0), m_pCanvas(0), m_pFileMenu(0),
273 m_pFilterMenu(0), m_bMinSpecified(false), m_bMaxSpecified(false),
274 m_iDefaultExportFormatID(ImageFile::EXPORT_FORMAT_PNG)
277 ImageFileView::~ImageFileView()
279 GetDocumentManager()->FileHistoryRemoveMenu (m_pFileMenu);
280 GetDocumentManager()->ActivateView(this, FALSE);
285 ImageFileView::OnProperties (wxCommandEvent& event)
287 const ImageFile& rIF = GetDocument()->getImageFile();
288 if (rIF.nx() == 0 || rIF.ny() == 0)
289 *theApp->getLog() << _T("Properties: empty imagefile\n");
291 const std::string rFilename (m_pFrame->GetTitle().mb_str(wxConvUTF8));
292 std::ostringstream os;
293 double min, max, mean, mode, median, stddev;
294 rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);
295 os << "Filename: " << rFilename << "\n";
296 os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";
302 os << "Minimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
303 if (rIF.isComplex()) {
304 rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);
305 os << "Imaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";
307 if (rIF.nLabels() > 0) {
308 rIF.printLabelsBrief (os);
310 *theApp->getLog() << _T(">>>>\n") << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("<<<<\n");
311 wxMessageDialog dialogMsg (getFrameForChild(), wxConvUTF8.cMB2WX(os.str().c_str()), _T("Imagefile Properties"), wxOK | wxICON_INFORMATION);
312 dialogMsg.ShowModal();
314 GetDocument()->Activate();
318 ImageFileView::OnScaleAuto (wxCommandEvent& event)
320 const ImageFile& rIF = GetDocument()->getImageFile();
321 double min, max, mean, mode, median, stddev;
322 rIF.statistics(min, max, mean, mode, median, stddev);
323 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
324 int iRetVal = dialogAutoScale.ShowModal();
325 if (iRetVal == wxID_OK) {
326 m_bMinSpecified = true;
327 m_bMaxSpecified = true;
329 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
332 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
333 OnUpdate(this, NULL);
334 GetDocument()->UpdateAllViews (this);
337 GetDocument()->Activate();
341 ImageFileView::OnScaleMinMax (wxCommandEvent& event)
343 const ImageFile& rIF = GetDocument()->getImageFile();
345 if (! m_bMinSpecified && ! m_bMaxSpecified)
346 rIF.getMinMax (min, max);
353 DialogGetMinMax dialogMinMax (getFrameForChild(), _T("Set Image Minimum & Maximum"), min, max);
354 int retVal = dialogMinMax.ShowModal();
355 if (retVal == wxID_OK) {
356 m_bMinSpecified = true;
357 m_bMaxSpecified = true;
358 m_dMinPixel = dialogMinMax.getMinimum();
359 m_dMaxPixel = dialogMinMax.getMaximum();
360 OnUpdate(this, NULL);
361 GetDocument()->UpdateAllViews (this);
363 GetDocument()->Activate();
367 ImageFileView::OnScaleFull (wxCommandEvent& event)
369 if (m_bMinSpecified || m_bMaxSpecified) {
370 m_bMinSpecified = false;
371 m_bMaxSpecified = false;
372 OnUpdate(this, NULL);
373 GetDocument()->UpdateAllViews (this);
375 GetDocument()->Activate();
379 ImageFileView::OnCompare (wxCommandEvent& event)
381 std::vector<ImageFileDocument*> vecIF;
382 theApp->getCompatibleImages (GetDocument(), vecIF);
384 if (vecIF.size() == 0) {
385 wxMessageBox(_T("There are no compatible image files open for comparision"), _T("No comparison images"));
387 DialogGetComparisonImage dialogGetCompare(getFrameForChild(), _T("Get Comparison Image"), vecIF, true);
389 if (dialogGetCompare.ShowModal() == wxID_OK) {
390 const ImageFile& rIF = GetDocument()->getImageFile();
391 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
392 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
393 std::ostringstream os;
394 double min, max, mean, mode, median, stddev;
395 rIF.statistics (min, max, mean, mode, median, stddev);
396 os << m_pFrame->GetTitle().mb_str(wxConvUTF8) << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
397 rCompareIF.statistics (min, max, mean, mode, median, stddev);
398 os << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8) << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
400 rIF.comparativeStatistics (rCompareIF, d, r, e);
401 os << "Comparative Statistics: d=" << d << ", r=" << r << ", e=" << e << "\n";
402 *theApp->getLog() << _T(">>>>\n") << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("<<<<\n");
403 if (dialogGetCompare.getMakeDifferenceImage()) {
404 ImageFile* pDifferenceImage = new ImageFile;
406 pDifferenceImage->setArraySize (rIF.nx(), rIF.ny());
407 if (! rIF.subtractImages (rCompareIF, *pDifferenceImage)) {
408 *theApp->getLog() << _T("Unable to subtract images\n");
409 delete pDifferenceImage;
412 ImageFileDocument* pDifferenceDoc = theApp->newImageDoc();
413 if (! pDifferenceDoc) {
414 sys_error (ERR_SEVERE, "Unable to create image file");
417 pDifferenceDoc->setImageFile (pDifferenceImage);
419 wxString s = m_pFrame->GetTitle() + _T(": ");
420 pDifferenceImage->labelsCopy (rIF, s.mb_str(wxConvUTF8));
421 s = dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
422 pDifferenceImage->labelsCopy (rCompareIF, s.mb_str(wxConvUTF8));
423 std::ostringstream osLabel;
424 osLabel << "Compare image " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str()
425 << " and " << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().c_str() << ": "
427 pDifferenceImage->labelAdd (os.str().c_str());
428 if (theApp->getAskDeleteNewDocs())
429 pDifferenceDoc->Modify (true);
430 OnUpdate(this, NULL);
431 pDifferenceDoc->UpdateAllViews(this);
432 pDifferenceDoc->getView()->setInitialClientSize();
433 pDifferenceDoc->Activate();
435 wxMessageBox(wxConvUTF8.cMB2WX(os.str().c_str()), _T("Image Comparison"));
441 ImageFileView::OnInvertValues (wxCommandEvent& event)
443 ImageFile& rIF = GetDocument()->getImageFile();
444 rIF.invertPixelValues (rIF);
445 rIF.labelAdd ("Invert Pixel Values");
446 if (theApp->getAskDeleteNewDocs())
447 GetDocument()->Modify (true);
448 OnUpdate(this, NULL);
449 GetDocument()->UpdateAllViews (this);
450 GetDocument()->Activate();
454 ImageFileView::OnSquare (wxCommandEvent& event)
456 ImageFile& rIF = GetDocument()->getImageFile();
458 rIF.labelAdd ("Square Pixel Values");
459 if (theApp->getAskDeleteNewDocs())
460 GetDocument()->Modify (true);
461 OnUpdate(this, NULL);
462 GetDocument()->UpdateAllViews (this);
463 GetDocument()->Activate();
467 ImageFileView::OnSquareRoot (wxCommandEvent& event)
469 ImageFile& rIF = GetDocument()->getImageFile();
471 rIF.labelAdd ("Square-root Pixel Values");
472 if (theApp->getAskDeleteNewDocs())
473 GetDocument()->Modify (true);
474 OnUpdate(this, NULL);
475 GetDocument()->UpdateAllViews (this);
476 GetDocument()->Activate();
480 ImageFileView::OnLog (wxCommandEvent& event)
482 ImageFile& rIF = GetDocument()->getImageFile();
484 rIF.labelAdd ("Logrithm base-e Pixel Values");
485 if (theApp->getAskDeleteNewDocs())
486 GetDocument()->Modify (true);
487 OnUpdate(this, NULL);
488 GetDocument()->UpdateAllViews (this);
489 GetDocument()->Activate();
493 ImageFileView::OnExp (wxCommandEvent& event)
495 ImageFile& rIF = GetDocument()->getImageFile();
497 rIF.labelAdd ("Exponent base-e Pixel Values");
498 if (theApp->getAskDeleteNewDocs())
499 GetDocument()->Modify (true);
500 OnUpdate(this, NULL);
501 GetDocument()->UpdateAllViews (this);
502 GetDocument()->Activate();
506 ImageFileView::OnAdd (wxCommandEvent& event)
508 std::vector<ImageFileDocument*> vecIF;
509 theApp->getCompatibleImages (GetDocument(), vecIF);
511 if (vecIF.size() == 0) {
512 wxMessageBox (_T("There are no compatible image files open for comparision"), _T("No comparison images"));
514 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Image to Add"), vecIF, false);
516 if (dialogGetCompare.ShowModal() == wxID_OK) {
517 ImageFile& rIF = GetDocument()->getImageFile();
518 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
519 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
520 ImageFileDocument* pNewDoc = theApp->newImageDoc();
522 sys_error (ERR_SEVERE, "Unable to create image file");
525 ImageFile& newImage = pNewDoc->getImageFile();
526 newImage.setArraySize (rIF.nx(), rIF.ny());
527 rIF.addImages (rRHSIF, newImage);
528 std::ostringstream os;
529 os << "Add image " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str() << " and "
530 << dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
531 wxString s = dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
532 newImage.labelsCopy (rIF, s.mb_str(wxConvUTF8));
533 s = dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
534 newImage.labelsCopy (rRHSIF, s.mb_str(wxConvUTF8));
535 newImage.labelAdd (os.str().c_str());
536 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
537 if (theApp->getAskDeleteNewDocs())
538 pNewDoc->Modify (true);
539 OnUpdate(this, NULL);
540 pNewDoc->UpdateAllViews (this);
541 pNewDoc->getView()->setInitialClientSize();
548 ImageFileView::OnSubtract (wxCommandEvent& event)
550 std::vector<ImageFileDocument*> vecIF;
551 theApp->getCompatibleImages (GetDocument(), vecIF);
553 if (vecIF.size() == 0) {
554 wxMessageBox (_T("There are no compatible image files open for comparision"), _T("No comparison images"));
556 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Image to Subtract"), vecIF, false);
558 if (dialogGetCompare.ShowModal() == wxID_OK) {
559 ImageFile& rIF = GetDocument()->getImageFile();
560 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
561 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
562 ImageFileDocument* pNewDoc = theApp->newImageDoc();
564 sys_error (ERR_SEVERE, "Unable to create image file");
567 ImageFile& newImage = pNewDoc->getImageFile();
568 newImage.setArraySize (rIF.nx(), rIF.ny());
569 rIF.subtractImages (rRHSIF, newImage);
570 std::ostringstream os;
571 os << "Subtract image " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str() << " and "
572 << dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
573 wxString s = dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
574 newImage.labelsCopy (rIF, s.mb_str(wxConvUTF8));
575 s = dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
576 newImage.labelsCopy (rRHSIF, s.mb_str(wxConvUTF8));
577 newImage.labelAdd (os.str().c_str());
578 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
579 if (theApp->getAskDeleteNewDocs())
580 pNewDoc->Modify (true);
581 OnUpdate(this, NULL);
582 pNewDoc->UpdateAllViews (this);
583 pNewDoc->getView()->setInitialClientSize();
590 ImageFileView::OnMultiply (wxCommandEvent& event)
592 std::vector<ImageFileDocument*> vecIF;
593 theApp->getCompatibleImages (GetDocument(), vecIF);
595 if (vecIF.size() == 0) {
596 wxMessageBox (_T("There are no compatible image files open for comparision"), _T("No comparison images"));
598 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Image to Multiply"), vecIF, false);
600 if (dialogGetCompare.ShowModal() == wxID_OK) {
601 ImageFile& rIF = GetDocument()->getImageFile();
602 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
603 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
604 ImageFileDocument* pNewDoc = theApp->newImageDoc();
606 sys_error (ERR_SEVERE, "Unable to create image file");
609 ImageFile& newImage = pNewDoc->getImageFile();
610 newImage.setArraySize (rIF.nx(), rIF.ny());
611 rIF.multiplyImages (rRHSIF, newImage);
612 std::ostringstream os;
613 os << "Multiply image " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str() << " and "
614 << dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
615 wxString s = dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
616 newImage.labelsCopy (rIF, s.mb_str(wxConvUTF8));
617 s = dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
618 newImage.labelsCopy (rRHSIF, s.mb_str(wxConvUTF8));
619 newImage.labelAdd (os.str().c_str());
620 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
621 if (theApp->getAskDeleteNewDocs())
622 pNewDoc->Modify (true);
623 OnUpdate(this, NULL);
624 pNewDoc->UpdateAllViews (this);
625 pNewDoc->getView()->setInitialClientSize();
632 ImageFileView::OnDivide (wxCommandEvent& event)
634 std::vector<ImageFileDocument*> vecIF;
635 theApp->getCompatibleImages (GetDocument(), vecIF);
637 if (vecIF.size() == 0) {
638 wxMessageBox (_T("There are no compatible image files open for comparision"), _T("No comparison images"));
640 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Image to Divide"), vecIF, false);
642 if (dialogGetCompare.ShowModal() == wxID_OK) {
643 ImageFile& rIF = GetDocument()->getImageFile();
644 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
645 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
646 ImageFileDocument* pNewDoc = theApp->newImageDoc();
648 sys_error (ERR_SEVERE, "Unable to create image file");
651 ImageFile& newImage = pNewDoc->getImageFile();
652 newImage.setArraySize (rIF.nx(), rIF.ny());
653 rIF.divideImages (rRHSIF, newImage);
654 std::ostringstream os;
655 os << "Divide image " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str() << " by "
656 << dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
657 wxString s = dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
658 newImage.labelsCopy (rIF, s.mb_str(wxConvUTF8));
659 s = dynamic_cast<wxFrame*>(pRHSDoc->GetFirstView()->GetFrame())->GetTitle() + _T(": ");
660 newImage.labelsCopy (rRHSIF, s.mb_str(wxConvUTF8));
661 newImage.labelAdd (os.str().c_str());
662 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
663 if (theApp->getAskDeleteNewDocs())
664 pNewDoc->Modify (true);
665 OnUpdate(this, NULL);
666 pNewDoc->UpdateAllViews (this);
667 pNewDoc->getView()->setInitialClientSize();
676 ImageFileView::OnFFT (wxCommandEvent& event)
678 ImageFile& rIF = GetDocument()->getImageFile();
680 rIF.labelAdd ("FFT Image");
681 m_bMinSpecified = false;
682 m_bMaxSpecified = false;
683 if (theApp->getAskDeleteNewDocs())
684 GetDocument()->Modify (true);
685 OnUpdate(this, NULL);
686 GetDocument()->UpdateAllViews (this);
687 GetDocument()->Activate();
691 ImageFileView::OnIFFT (wxCommandEvent& event)
693 ImageFile& rIF = GetDocument()->getImageFile();
695 rIF.labelAdd ("IFFT Image");
696 m_bMinSpecified = false;
697 m_bMaxSpecified = false;
698 if (theApp->getAskDeleteNewDocs())
699 GetDocument()->Modify (true);
700 OnUpdate(this, NULL);
701 GetDocument()->UpdateAllViews (this);
702 GetDocument()->Activate();
706 ImageFileView::OnFFTRows (wxCommandEvent& event)
708 ImageFile& rIF = GetDocument()->getImageFile();
710 rIF.labelAdd ("FFT Rows");
711 m_bMinSpecified = false;
712 m_bMaxSpecified = false;
713 if (theApp->getAskDeleteNewDocs())
714 GetDocument()->Modify (true);
715 OnUpdate(this, NULL);
716 GetDocument()->UpdateAllViews (this);
717 GetDocument()->Activate();
721 ImageFileView::OnIFFTRows (wxCommandEvent& event)
723 ImageFile& rIF = GetDocument()->getImageFile();
725 rIF.labelAdd ("IFFT Rows");
726 m_bMinSpecified = false;
727 m_bMaxSpecified = false;
728 if (theApp->getAskDeleteNewDocs())
729 GetDocument()->Modify (true);
730 OnUpdate(this, NULL);
731 GetDocument()->UpdateAllViews (this);
732 GetDocument()->Activate();
736 ImageFileView::OnFFTCols (wxCommandEvent& event)
738 ImageFile& rIF = GetDocument()->getImageFile();
740 rIF.labelAdd ("FFT Columns");
741 m_bMinSpecified = false;
742 m_bMaxSpecified = false;
743 if (theApp->getAskDeleteNewDocs())
744 GetDocument()->Modify (true);
745 OnUpdate(this, NULL);
746 GetDocument()->UpdateAllViews (this);
747 GetDocument()->Activate();
751 ImageFileView::OnIFFTCols (wxCommandEvent& event)
753 ImageFile& rIF = GetDocument()->getImageFile();
755 rIF.labelAdd ("IFFT Columns");
756 m_bMinSpecified = false;
757 m_bMaxSpecified = false;
758 if (theApp->getAskDeleteNewDocs())
759 GetDocument()->Modify (true);
760 OnUpdate(this, NULL);
761 GetDocument()->UpdateAllViews (this);
762 GetDocument()->Activate();
767 ImageFileView::OnFourier (wxCommandEvent& event)
769 ImageFile& rIF = GetDocument()->getImageFile();
770 wxProgressDialog dlgProgress (_T("Fourier"), _T("Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
772 rIF.labelAdd ("Fourier Image");
773 m_bMinSpecified = false;
774 m_bMaxSpecified = false;
775 if (theApp->getAskDeleteNewDocs())
776 GetDocument()->Modify (true);
777 OnUpdate(this, NULL);
778 GetDocument()->UpdateAllViews (this);
779 GetDocument()->Activate();
783 ImageFileView::OnInverseFourier (wxCommandEvent& event)
785 ImageFile& rIF = GetDocument()->getImageFile();
786 wxProgressDialog dlgProgress (_T("Inverse Fourier"), _T("Inverse Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
787 rIF.inverseFourier (rIF);
788 rIF.labelAdd ("Inverse Fourier Image");
789 m_bMinSpecified = false;
790 m_bMaxSpecified = false;
791 if (theApp->getAskDeleteNewDocs())
792 GetDocument()->Modify (true);
793 OnUpdate(this, NULL);
794 GetDocument()->UpdateAllViews (this);
795 GetDocument()->Activate();
799 ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)
801 ImageFile& rIF = GetDocument()->getImageFile();
802 Fourier::shuffleNaturalToFourierOrder (rIF);
803 rIF.labelAdd ("Shuffle Natural To Fourier Order");
804 m_bMinSpecified = false;
805 m_bMaxSpecified = false;
806 if (theApp->getAskDeleteNewDocs())
807 GetDocument()->Modify (true);
808 OnUpdate(this, NULL);
809 GetDocument()->UpdateAllViews (this);
810 GetDocument()->Activate();
814 ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)
816 ImageFile& rIF = GetDocument()->getImageFile();
817 Fourier::shuffleFourierToNaturalOrder (rIF);
818 rIF.labelAdd ("Shuffle Fourier To Natural Order");
819 m_bMinSpecified = false;
820 m_bMaxSpecified = false;
821 if (theApp->getAskDeleteNewDocs())
822 GetDocument()->Modify (true);
823 OnUpdate(this, NULL);
824 GetDocument()->UpdateAllViews (this);
825 GetDocument()->Activate();
829 ImageFileView::OnMagnitude (wxCommandEvent& event)
831 ImageFile& rIF = GetDocument()->getImageFile();
833 rIF.labelAdd ("Magnitude");
834 m_bMinSpecified = false;
835 m_bMaxSpecified = false;
836 if (theApp->getAskDeleteNewDocs())
837 GetDocument()->Modify (true);
838 OnUpdate(this, NULL);
839 GetDocument()->UpdateAllViews (this);
840 GetDocument()->Activate();
844 ImageFileView::OnPhase (wxCommandEvent& event)
846 ImageFile& rIF = GetDocument()->getImageFile();
847 if (rIF.isComplex()) {
849 rIF.labelAdd ("Phase of complex-image");
850 m_bMinSpecified = false;
851 m_bMaxSpecified = false;
852 if (theApp->getAskDeleteNewDocs())
853 GetDocument()->Modify (true);
854 OnUpdate(this, NULL);
855 GetDocument()->UpdateAllViews (this);
857 GetDocument()->Activate();
861 ImageFileView::OnReal (wxCommandEvent& event)
863 ImageFile& rIF = GetDocument()->getImageFile();
864 if (rIF.isComplex()) {
866 rIF.labelAdd ("Real component of complex-image");
867 m_bMinSpecified = false;
868 m_bMaxSpecified = false;
869 if (theApp->getAskDeleteNewDocs())
870 GetDocument()->Modify (true);
871 OnUpdate(this, NULL);
872 GetDocument()->UpdateAllViews (this);
874 GetDocument()->Activate();
878 ImageFileView::OnImaginary (wxCommandEvent& event)
880 ImageFile& rIF = GetDocument()->getImageFile();
881 if (rIF.isComplex()) {
883 rIF.labelAdd ("Imaginary component of complex-image");
884 m_bMinSpecified = false;
885 m_bMaxSpecified = false;
886 if (theApp->getAskDeleteNewDocs())
887 GetDocument()->Modify (true);
888 OnUpdate(this, NULL);
889 GetDocument()->UpdateAllViews (this);
891 GetDocument()->Activate();
896 ImageFileView::CreateCanvas (wxFrame* parent)
898 ImageFileCanvas* pCanvas = new ImageFileCanvas (this, parent, wxPoint(-1,-1),
900 pCanvas->SetBackgroundColour(*wxWHITE);
901 pCanvas->ClearBackground();
911 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
914 wxDocMDIChildFrame* subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, _T("ImageFile Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
916 wxDocChildFrame* subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, _T("ImageFile Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
918 theApp->setIconForFrame (subframe);
920 m_pFileMenu = new wxMenu;
921 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
922 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
923 m_pFileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
924 m_pFileMenu->Append(wxID_SAVE, _T("&Save\tCtrl-S"));
925 m_pFileMenu->Append(wxID_SAVEAS, _T("Save &As..."));
926 m_pFileMenu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
927 m_pFileMenu->Append(wxID_REVERT, _T("Re&vert"));
929 m_pFileMenu->AppendSeparator();
930 m_pFileMenu->Append(IFMENU_FILE_PROPERTIES, _T("P&roperties\tCtrl-I"));
931 m_pFileMenu->Append(IFMENU_FILE_EXPORT, _T("Expor&t..."));
933 m_pFileMenu->AppendSeparator();
934 m_pFileMenu->Append(wxID_PRINT, _T("&Print..."));
935 m_pFileMenu->Append(wxID_PRINT_SETUP, _T("Print &Setup..."));
936 m_pFileMenu->Append(wxID_PREVIEW, _T("Print Preview"));
937 m_pFileMenu->AppendSeparator();
938 m_pFileMenu->Append(MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
939 m_pFileMenu->AppendSeparator();
940 m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
941 m_pFileMenu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
942 GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
943 GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
945 wxMenu* edit_menu = new wxMenu;
946 edit_menu->Append(IFMENU_EDIT_COPY, _T("Copy\tCtrl-C"));
947 edit_menu->Append(IFMENU_EDIT_CUT, _T("Cut\tCtrl-X"));
948 edit_menu->Append(IFMENU_EDIT_PASTE, _T("Paste\tCtrl-V"));
950 wxMenu *view_menu = new wxMenu;
951 view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, _T("Display Scale S&et...\tCtrl-E"));
952 view_menu->Append(IFMENU_VIEW_SCALE_AUTO, _T("Display Scale &Auto...\tCtrl-A"));
953 view_menu->Append(IFMENU_VIEW_SCALE_FULL, _T("Display F&ull Scale\tCtrl-U"));
955 m_pFilterMenu = new wxMenu;
956 m_pFilterMenu->Append (IFMENU_FILTER_INVERTVALUES, _T("In&vert Values"));
957 m_pFilterMenu->Append (IFMENU_FILTER_SQUARE, _T("&Square"));
958 m_pFilterMenu->Append (IFMENU_FILTER_SQRT, _T("Square &Root"));
959 m_pFilterMenu->Append (IFMENU_FILTER_LOG, _T("&Log"));
960 m_pFilterMenu->Append (IFMENU_FILTER_EXP, _T("E&xp"));
961 m_pFilterMenu->AppendSeparator();
963 m_pFilterMenu->Append (IFMENU_FILTER_FFT, _T("2-D &FFT\tCtrl-2"));
964 m_pFilterMenu->Append (IFMENU_FILTER_IFFT, _T("2-D &IFFT\tAlt-2"));
965 m_pFilterMenu->Append (IFMENU_FILTER_FFT_ROWS, _T("FFT Rows"));
966 m_pFilterMenu->Append (IFMENU_FILTER_IFFT_ROWS, _T("IFFT Rows"));
967 m_pFilterMenu->Append (IFMENU_FILTER_FFT_COLS, _T("FFT Columns"));
968 m_pFilterMenu->Append (IFMENU_FILTER_IFFT_COLS, _T("IFFT Columns"));
969 m_pFilterMenu->Append (IFMENU_FILTER_FOURIER, _T("2-D F&ourier"));
970 m_pFilterMenu->Append (IFMENU_FILTER_INVERSE_FOURIER, _T("2-D Inverse Fo&urier"));
972 m_pFilterMenu->Append (IFMENU_FILTER_FOURIER, _T("&Fourier"));
973 m_pFilterMenu->Append (IFMENU_FILTER_INVERSE_FOURIER, _T("&Inverse Fourier"));
975 m_pFilterMenu->Append (IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, _T("Shuffl&e Fourier to Natural Order"));
976 m_pFilterMenu->Append (IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, _T("Shuffle &Natural to Fourier Order"));
977 m_pFilterMenu->AppendSeparator();
978 m_pFilterMenu->Append (IFMENU_FILTER_MAGNITUDE, _T("&Magnitude"));
979 m_pFilterMenu->Append (IFMENU_FILTER_PHASE, _T("&Phase"));
980 m_pFilterMenu->Append (IFMENU_FILTER_REAL, _T("Re&al"));
981 m_pFilterMenu->Append (IFMENU_FILTER_IMAGINARY, _T("Ima&ginary"));
983 wxMenu* image_menu = new wxMenu;
984 image_menu->Append (IFMENU_IMAGE_ADD, _T("&Add..."));
985 image_menu->Append (IFMENU_IMAGE_SUBTRACT, _T("&Subtract..."));
986 image_menu->Append (IFMENU_IMAGE_MULTIPLY, _T("&Multiply..."));
987 image_menu->Append (IFMENU_IMAGE_DIVIDE, _T("&Divide..."));
988 image_menu->AppendSeparator();
989 image_menu->Append (IFMENU_IMAGE_SCALESIZE, _T("S&cale Size..."));
991 image_menu->Append (IFMENU_IMAGE_CONVERT3D, _T("Convert &3-D\tCtrl-3"));
994 m_pMenuAnalyze = new wxMenu;
995 m_pMenuAnalyze->Append (IFMENU_PLOT_ROW, _T("Plot &Row"));
996 m_pMenuAnalyze->Append (IFMENU_PLOT_COL, _T("Plot &Column"));
997 m_pMenuAnalyze->Append (IFMENU_PLOT_HISTOGRAM, _T("Plot &Histogram"));
998 m_pMenuAnalyze->AppendSeparator();
999 m_pMenuAnalyze->Append (IFMENU_PLOT_FFT_ROW, _T("P&lot FFT Row"));
1000 m_pMenuAnalyze->Append (IFMENU_PLOT_FFT_COL, _T("Plo&t FFT Column"));
1001 m_pMenuAnalyze->AppendSeparator();
1002 m_pMenuAnalyze->Append (IFMENU_COMPARE_IMAGES, _T("Compare &Images..."));
1003 m_pMenuAnalyze->Append (IFMENU_COMPARE_ROW, _T("Compare Ro&w"));
1004 m_pMenuAnalyze->Append (IFMENU_COMPARE_COL, _T("Compare Colu&mn"));
1005 m_pMenuAnalyze->Enable (IFMENU_PLOT_ROW, false);
1006 m_pMenuAnalyze->Enable (IFMENU_PLOT_COL, false);
1007 m_pMenuAnalyze->Enable (IFMENU_COMPARE_ROW, false);
1008 m_pMenuAnalyze->Enable (IFMENU_COMPARE_COL, false);
1009 m_pMenuAnalyze->Enable (IFMENU_PLOT_FFT_ROW, false);
1010 m_pMenuAnalyze->Enable (IFMENU_PLOT_FFT_COL, false);
1012 wxMenu *help_menu = new wxMenu;
1013 help_menu->Append(MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
1014 help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
1015 help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
1016 help_menu->Append(MAINMENU_HELP_ABOUT, _T("&About"));
1018 wxMenuBar *menu_bar = new wxMenuBar;
1020 menu_bar->Append(m_pFileMenu, _T("&File"));
1021 menu_bar->Append(edit_menu, _T("&Edit"));
1022 menu_bar->Append(view_menu, _T("&View"));
1023 menu_bar->Append(image_menu, _T("&Image"));
1024 menu_bar->Append(m_pFilterMenu, _T("Fi<er"));
1025 menu_bar->Append(m_pMenuAnalyze, _T("&Analyze"));
1026 menu_bar->Append(help_menu, _T("&Help"));
1028 subframe->SetMenuBar(menu_bar);
1030 subframe->Centre(wxBOTH);
1032 wxAcceleratorEntry accelEntries[10];
1033 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('A'), IFMENU_VIEW_SCALE_AUTO);
1034 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('U'), IFMENU_VIEW_SCALE_FULL);
1035 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('E'), IFMENU_VIEW_SCALE_MINMAX);
1036 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('I'), IFMENU_FILE_PROPERTIES);
1037 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('C'), IFMENU_EDIT_COPY);
1038 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('X'), IFMENU_EDIT_CUT);
1039 accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('V'), IFMENU_EDIT_PASTE);
1042 accelEntries[iEntry++].Set (wxACCEL_CTRL, static_cast<int>('2'), IFMENU_FILTER_FFT);
1043 accelEntries[iEntry++].Set (wxACCEL_ALT, static_cast<int>('2'), IFMENU_FILTER_IFFT);
1046 accelEntries[iEntry++].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
1049 wxAcceleratorTable accelTable (iEntry, accelEntries);
1050 subframe->SetAcceleratorTable (accelTable);
1057 ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
1059 m_bMinSpecified = false;
1060 m_bMaxSpecified = false;
1061 m_dAutoScaleFactor = 1.;
1063 m_pFrame = CreateChildFrame(doc, this);
1064 SetFrame (m_pFrame);
1065 m_pCanvas = CreateCanvas (m_pFrame);
1066 m_pFrame->SetClientSize (m_pCanvas->GetBestSize());
1067 m_pCanvas->SetClientSize (m_pCanvas->GetBestSize());
1068 m_pFrame->SetTitle(_T("ImageFileView"));
1070 m_pFrame->Show(true);
1077 ImageFileView::setInitialClientSize ()
1079 if (m_pFrame && m_pCanvas) {
1080 wxSize bestSize = m_pCanvas->GetBestSize();
1082 m_pFrame->SetClientSize (bestSize);
1083 m_pFrame->Show (true);
1084 m_pFrame->SetFocus();
1089 ImageFileView::OnDraw (wxDC* dc)
1091 if (m_pBitmap && m_pBitmap->Ok()) {
1093 *theApp->getLog() << _T("Drawing bitmap\n");
1095 dc->DrawBitmap(*m_pBitmap, 0, 0, false);
1098 int xCursor, yCursor;
1099 if (m_pCanvas->GetCurrentCursor (xCursor, yCursor))
1100 m_pCanvas->DrawRubberBandCursor (*dc, xCursor, yCursor);
1105 ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1107 const ImageFile& rIF = GetDocument()->getImageFile();
1108 if (m_pFilterMenu && rIF.isComplex()) {
1109 m_pFilterMenu->Enable(IFMENU_FILTER_REAL, true);
1110 m_pFilterMenu->Enable(IFMENU_FILTER_IMAGINARY, true);
1111 m_pFilterMenu->Enable(IFMENU_FILTER_PHASE, true);
1113 m_pFilterMenu->Enable(IFMENU_FILTER_REAL, false);
1114 m_pFilterMenu->Enable(IFMENU_FILTER_IMAGINARY, false);
1115 m_pFilterMenu->Enable(IFMENU_FILTER_PHASE, false);
1117 ImageFileArrayConst v = rIF.getArray();
1120 if (v != NULL && nx != 0 && ny != 0) {
1121 if (! m_bMinSpecified || ! m_bMaxSpecified) {
1123 rIF.getMinMax (min, max);
1124 if (! m_bMinSpecified)
1126 if (! m_bMaxSpecified)
1129 double scaleWidth = m_dMaxPixel - m_dMinPixel;
1131 unsigned char* imageData = new unsigned char [nx * ny * 3];
1133 sys_error (ERR_SEVERE, "Unable to allocate memory for Image display");
1136 for (int ix = 0; ix < nx; ix++) {
1137 for (int iy = 0; iy < ny; iy++) {
1138 double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
1139 int intensity = static_cast<int>(scaleValue + 0.5);
1140 intensity = clamp (intensity, 0, 255);
1141 int baseAddr = ((ny - 1 - iy) * nx + ix) * 3;
1142 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
1145 wxImage image (nx, ny, imageData, true);
1151 *theApp->getLog() << _T("Making new bitmap\n");
1153 m_pBitmap = new wxBitmap (image);
1155 m_pCanvas->SetScrollbars(20, 20, nx/20, ny/20);
1156 m_pCanvas->SetBackgroundColour(*wxWHITE);
1160 m_pCanvas->Refresh();
1164 ImageFileView::OnClose (bool deleteWindow)
1166 if (! GetDocument() || ! GetDocument()->Close())
1171 m_pCanvas->setView(NULL);
1174 wxString s(theApp->GetAppName());
1176 m_pFrame->SetTitle(s);
1183 if (GetDocument() && GetDocument()->getBadFileOpen())
1184 ::wxYield(); // wxWindows bug workaround
1191 ImageFileView::OnEditCopy (wxCommandEvent& event)
1193 wxBitmapDataObject *pBitmapObject = new wxBitmapDataObject;
1196 pBitmapObject->SetBitmap (*m_pBitmap);
1198 if (wxTheClipboard->Open()) {
1199 wxTheClipboard->SetData (pBitmapObject);
1200 wxTheClipboard->Close();
1205 ImageFileView::OnEditCut (wxCommandEvent& event)
1208 ImageFile& rIF = GetDocument()->getImageFile();
1211 ImageFile* pIF = new ImageFile (nx, ny);
1212 pIF->arrayDataClear();
1213 GetDocument()->setImageFile (pIF); // deletes old IF
1214 OnUpdate(this, NULL);
1215 GetDocument()->UpdateAllViews();
1216 if (theApp->getAskDeleteNewDocs())
1217 GetDocument()->Modify (true);
1221 ImageFileView::OnEditPaste (wxCommandEvent& event)
1223 ImageFile& rIF = GetDocument()->getImageFile();
1225 if (wxTheClipboard->Open()) {
1227 if (wxTheClipboard->IsSupported (wxDF_BITMAP)) {
1228 wxBitmapDataObject bitmapObject;
1229 wxTheClipboard->GetData (bitmapObject);
1230 bitmap = bitmapObject.GetBitmap ();
1232 wxTheClipboard->Close();
1236 bool bMonochrome = false;
1238 if (bitmap.Ok() == true && bitmap.GetWidth() == nx && bitmap.GetHeight() == ny) {
1239 wxImage image (bitmap.ConvertToImage());
1240 double dScale3 = 3 * 255;
1241 unsigned char* pixels = image.GetData();
1242 ImageFileArray v = rIF.getArray();
1243 for (unsigned int ix = 0; ix < rIF.nx(); ix++) {
1244 for (unsigned int iy = 0; iy < rIF.ny(); iy++) {
1245 unsigned int iBase = 3 * (iy * nx + ix);
1246 if (ix == 0 && iy == 0 && (pixels[iBase] == pixels[iBase+1] && pixels[iBase+1] == pixels[iBase+2]))
1249 v[ix][ny - 1 - iy] = (pixels[iBase]+pixels[iBase+1]+pixels[iBase+2]) / dScale3;
1251 double dR = pixels[iBase] / 255.;
1252 double dG = pixels[iBase+1] / 255.;
1253 double dB = pixels[iBase+2] / 255.;
1254 v[ix][ny - 1 - iy] = ImageFile::colorToGrayscale (dR, dG, dB);
1258 OnUpdate(this, NULL);
1259 GetDocument()->UpdateAllViews();
1260 if (theApp->getAskDeleteNewDocs())
1261 GetDocument()->Modify(true);
1267 ImageFileView::OnExport (wxCommandEvent& event)
1269 ImageFile& rIF = GetDocument()->getImageFile();
1270 ImageFileArrayConst v = rIF.getArray();
1273 if (v != NULL && nx != 0 && ny != 0) {
1274 if (! m_bMinSpecified || ! m_bMaxSpecified) {
1276 rIF.getMinMax (min, max);
1277 if (! m_bMinSpecified)
1279 if (! m_bMaxSpecified)
1283 DialogExportParameters dialogExport (getFrameForChild(), m_iDefaultExportFormatID);
1284 if (dialogExport.ShowModal() == wxID_OK) {
1285 wxString strFormatName (dialogExport.getFormatName (), wxConvUTF8);
1286 m_iDefaultExportFormatID = ImageFile::convertExportFormatNameToID (strFormatName.mb_str(wxConvUTF8));
1289 wxString strWildcard;
1290 if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_PGMASCII) {
1291 strExt = _T(".pgm");
1292 strWildcard = _T("PGM Files (*.pgm)|*.pgm");
1295 else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_PNG16) {
1296 strExt = _T(".png");
1297 strWildcard = _T("PNG Files (*.png)|*.png");
1300 #ifdef HAVE_CTN_DICOM
1301 else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_DICOM) {
1303 strWildcard = _T("DICOM Files (*.*)|*.*");
1306 else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_TEXT) {
1307 strExt = _T(".txt");
1308 strWildcard = _T("Text (*.txt)|*.txt");
1312 strWildcard = _T("Miscellaneous (*.*)|*.*");
1315 #if WXWIN_COMPATIBILITY_2_4
1316 const wxString& strFilename = wxFileSelector (_T("Export Filename"), _T(""),
1317 _T(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);
1319 const wxString& strFilename = wxFileSelector (_T("Export Filename"), _T(""),
1320 _T(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxSAVE);
1323 rIF.exportImage (strFormatName.mb_str(wxConvUTF8), strFilename.mb_str(wxConvUTF8), 1, 1, m_dMinPixel, m_dMaxPixel);
1324 *theApp->getLog() << _T("Exported file ") << strFilename << _T("\n");
1331 ImageFileView::OnScaleSize (wxCommandEvent& event)
1333 ImageFile& rIF = GetDocument()->getImageFile();
1334 unsigned int iOldNX = rIF.nx();
1335 unsigned int iOldNY = rIF.ny();
1337 DialogGetXYSize dialogGetXYSize (getFrameForChild(), _T("Set New X & Y Dimensions"), iOldNX, iOldNY);
1338 if (dialogGetXYSize.ShowModal() == wxID_OK) {
1339 unsigned int iNewNX = dialogGetXYSize.getXSize();
1340 unsigned int iNewNY = dialogGetXYSize.getYSize();
1341 std::ostringstream os;
1342 os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";
1343 ImageFileDocument* pScaledDoc = theApp->newImageDoc();
1345 sys_error (ERR_SEVERE, "Unable to create image file");
1348 ImageFile& rScaledIF = pScaledDoc->getImageFile();
1349 rScaledIF.setArraySize (iNewNX, iNewNY);
1350 rScaledIF.labelsCopy (rIF);
1351 rScaledIF.labelAdd (os.str().c_str());
1352 rIF.scaleImage (rScaledIF);
1353 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1354 if (theApp->getAskDeleteNewDocs())
1355 pScaledDoc->Modify (true);
1356 OnUpdate(this, NULL);
1357 pScaledDoc->UpdateAllViews (this);
1358 pScaledDoc->getView()->setInitialClientSize();
1359 pScaledDoc->Activate();
1365 ImageFileView::OnConvert3d (wxCommandEvent& event)
1367 ImageFile& rIF = GetDocument()->getImageFile();
1368 Graph3dFileDocument* pGraph3d = theApp->newGraph3dDoc();
1369 pGraph3d->getView()->getFrame()->Show (false);
1370 pGraph3d->setBadFileOpen();
1371 pGraph3d->createFromImageFile (rIF);
1372 pGraph3d->UpdateAllViews();
1373 pGraph3d->getView()->getFrame()->Show (true);
1374 pGraph3d->getView()->Activate(true);
1376 pGraph3d->getView()->getCanvas()->SetFocus();
1381 ImageFileView::OnPlotRow (wxCommandEvent& event)
1383 int xCursor, yCursor;
1384 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1385 wxMessageBox (_T("No row selected. Please use left mouse button on image to select column"),_T("Error"));
1389 const ImageFile& rIF = GetDocument()->getImageFile();
1390 ImageFileArrayConst v = rIF.getArray();
1391 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1395 if (v != NULL && yCursor < ny) {
1396 double* pX = new double [nx];
1397 double* pYReal = new double [nx];
1398 double *pYImag = NULL;
1399 double *pYMag = NULL;
1400 if (rIF.isComplex()) {
1401 pYImag = new double [nx];
1402 pYMag = new double [nx];
1404 for (int i = 0; i < nx; i++) {
1406 pYReal[i] = v[i][yCursor];
1407 if (rIF.isComplex()) {
1408 pYImag[i] = vImag[i][yCursor];
1409 pYMag[i] = ::sqrt (v[i][yCursor] * v[i][yCursor] + vImag[i][yCursor] * vImag[i][yCursor]);
1412 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1414 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1416 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1417 std::ostringstream os;
1418 os << "Row " << yCursor;
1419 std::string title("title ");
1421 rPlotFile.addEzsetCommand (title.c_str());
1422 rPlotFile.addEzsetCommand ("xlabel Column");
1423 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1424 rPlotFile.addEzsetCommand ("lxfrac 0");
1425 rPlotFile.addEzsetCommand ("box");
1426 rPlotFile.addEzsetCommand ("grid");
1427 rPlotFile.addEzsetCommand ("curve 1");
1428 rPlotFile.addEzsetCommand ("color 1");
1429 if (rIF.isComplex()) {
1430 rPlotFile.addEzsetCommand ("dash 1");
1431 rPlotFile.addEzsetCommand ("curve 2");
1432 rPlotFile.addEzsetCommand ("color 4");
1433 rPlotFile.addEzsetCommand ("dash 3");
1434 rPlotFile.addEzsetCommand ("curve 3");
1435 rPlotFile.addEzsetCommand ("color 0");
1436 rPlotFile.addEzsetCommand ("solid");
1437 rPlotFile.setCurveSize (4, nx);
1439 rPlotFile.setCurveSize (2, nx);
1440 rPlotFile.addColumn (0, pX);
1441 rPlotFile.addColumn (1, pYReal);
1442 if (rIF.isComplex()) {
1443 rPlotFile.addColumn (2, pYImag);
1444 rPlotFile.addColumn (3, pYMag);
1446 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1447 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1448 os << " Plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
1449 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1450 rPlotFile.addDescription (os.str().c_str());
1454 if (rIF.isComplex()) {
1458 if (theApp->getAskDeleteNewDocs())
1459 pPlotDoc->Modify (true);
1460 pPlotDoc->getView()->getFrame()->Show(true);
1461 pPlotDoc->UpdateAllViews ();
1462 pPlotDoc->Activate();
1467 ImageFileView::OnPlotCol (wxCommandEvent& event)
1469 int xCursor, yCursor;
1470 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1471 wxMessageBox (_T("No column selected. Please use left mouse button on image to select column"),_T("Error"));
1475 const ImageFile& rIF = GetDocument()->getImageFile();
1476 ImageFileArrayConst v = rIF.getArray();
1477 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1481 if (v != NULL && xCursor < nx) {
1482 double* pX = new double [ny];
1483 double* pYReal = new double [ny];
1484 double* pYImag = NULL;
1485 double* pYMag = NULL;
1486 if (rIF.isComplex()) {
1487 pYImag = new double [ny];
1488 pYMag = new double [ny];
1490 for (int i = 0; i < ny; i++) {
1492 pYReal[i] = v[xCursor][i];
1493 if (rIF.isComplex()) {
1494 pYImag[i] = vImag[xCursor][i];
1495 pYMag[i] = ::sqrt (v[xCursor][i] * v[xCursor][i] + vImag[xCursor][i] * vImag[xCursor][i]);
1498 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1500 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1502 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1503 std::ostringstream os;
1504 os << "Column " << xCursor;
1505 std::string title("title ");
1507 rPlotFile.addEzsetCommand (title.c_str());
1508 rPlotFile.addEzsetCommand ("xlabel Row");
1509 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1510 rPlotFile.addEzsetCommand ("lxfrac 0");
1511 rPlotFile.addEzsetCommand ("box");
1512 rPlotFile.addEzsetCommand ("grid");
1513 rPlotFile.addEzsetCommand ("curve 1");
1514 rPlotFile.addEzsetCommand ("color 1");
1515 if (rIF.isComplex()) {
1516 rPlotFile.addEzsetCommand ("dash 1");
1517 rPlotFile.addEzsetCommand ("curve 2");
1518 rPlotFile.addEzsetCommand ("color 4");
1519 rPlotFile.addEzsetCommand ("dash 3");
1520 rPlotFile.addEzsetCommand ("curve 3");
1521 rPlotFile.addEzsetCommand ("color 0");
1522 rPlotFile.addEzsetCommand ("solid");
1523 rPlotFile.setCurveSize (4, ny);
1525 rPlotFile.setCurveSize (2, ny);
1526 rPlotFile.addColumn (0, pX);
1527 rPlotFile.addColumn (1, pYReal);
1528 if (rIF.isComplex()) {
1529 rPlotFile.addColumn (2, pYImag);
1530 rPlotFile.addColumn (3, pYMag);
1532 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1533 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1534 os << " Plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
1535 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1536 rPlotFile.addDescription (os.str().c_str());
1540 if (rIF.isComplex()) {
1544 if (theApp->getAskDeleteNewDocs())
1545 pPlotDoc->Modify (true);
1546 pPlotDoc->getView()->getFrame()->Show(true);
1547 pPlotDoc->UpdateAllViews ();
1548 pPlotDoc->Activate();
1554 ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
1556 int xCursor, yCursor;
1557 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1558 wxMessageBox (_T("No row selected. Please use left mouse button on image to select column"),_T("Error"));
1562 const ImageFile& rIF = GetDocument()->getImageFile();
1563 ImageFileArrayConst v = rIF.getArray();
1564 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1568 if (v != NULL && yCursor < ny) {
1569 fftw_complex* pcIn = static_cast<fftw_complex*>(fftw_malloc (sizeof(fftw_complex) * nx));
1572 for (i = 0; i < nx; i++) {
1573 pcIn[i][0] = v[i][yCursor];
1574 if (rIF.isComplex())
1575 pcIn[i][1] = vImag[i][yCursor];
1580 fftw_plan plan = fftw_plan_dft_1d (nx, pcIn, pcIn, FFTW_FORWARD, FFTW_ESTIMATE);
1581 fftw_execute (plan);
1582 fftw_destroy_plan (plan);
1584 double* pX = new double [nx];
1585 double* pYReal = new double [nx];
1586 double* pYImag = new double [nx];
1587 double* pYMag = new double [nx];
1588 for (i = 0; i < nx; i++) {
1590 pYReal[i] = pcIn[i][0] / nx;
1591 pYImag[i] = pcIn[i][1] / nx;
1592 pYMag[i] = ::sqrt (pcIn[i][0] * pcIn[i][0] + pcIn[i][1] * pcIn[i][1]);
1594 Fourier::shuffleFourierToNaturalOrder (pYReal, nx);
1595 Fourier::shuffleFourierToNaturalOrder (pYImag, nx);
1596 Fourier::shuffleFourierToNaturalOrder (pYMag, nx);
1598 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1600 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1602 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1603 std::ostringstream os;
1604 os << "Row " << yCursor;
1605 std::string title("title ");
1607 rPlotFile.addEzsetCommand (title.c_str());
1608 rPlotFile.addEzsetCommand ("xlabel Column");
1609 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1610 rPlotFile.addEzsetCommand ("lxfrac 0");
1611 rPlotFile.addEzsetCommand ("curve 1");
1612 rPlotFile.addEzsetCommand ("color 1");
1613 rPlotFile.addEzsetCommand ("dash 1");
1614 rPlotFile.addEzsetCommand ("curve 2");
1615 rPlotFile.addEzsetCommand ("color 4");
1616 rPlotFile.addEzsetCommand ("dash 3");
1617 rPlotFile.addEzsetCommand ("curve 3");
1618 rPlotFile.addEzsetCommand ("color 0");
1619 rPlotFile.addEzsetCommand ("solid");
1620 rPlotFile.addEzsetCommand ("box");
1621 rPlotFile.addEzsetCommand ("grid");
1622 rPlotFile.setCurveSize (4, nx);
1623 rPlotFile.addColumn (0, pX);
1624 rPlotFile.addColumn (1, pYReal);
1625 rPlotFile.addColumn (2, pYImag);
1626 rPlotFile.addColumn (3, pYMag);
1627 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1628 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1629 os << " FFT Plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
1630 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1631 rPlotFile.addDescription (os.str().c_str());
1639 if (theApp->getAskDeleteNewDocs())
1640 pPlotDoc->Modify (true);
1641 pPlotDoc->getView()->getFrame()->Show(true);
1642 pPlotDoc->UpdateAllViews ();
1643 pPlotDoc->Activate();
1648 ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
1650 int xCursor, yCursor;
1651 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1652 wxMessageBox (_T("No column selected. Please use left mouse button on image to select column"),_T("Error"));
1656 const ImageFile& rIF = GetDocument()->getImageFile();
1657 ImageFileArrayConst v = rIF.getArray();
1658 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1662 if (v != NULL && xCursor < nx) {
1663 fftw_complex* pcIn = new fftw_complex [ny];
1664 double *pdTemp = new double [ny];
1667 for (i = 0; i < ny; i++)
1668 pdTemp[i] = v[xCursor][i];
1669 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1670 for (i = 0; i < ny; i++)
1671 pcIn[i][0] = pdTemp[i];
1673 for (i = 0; i < ny; i++) {
1674 if (rIF.isComplex())
1675 pdTemp[i] = vImag[xCursor][i];
1679 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1680 for (i = 0; i < ny; i++)
1681 pcIn[i][1] = pdTemp[i];
1683 fftw_plan plan = fftw_plan_dft_1d (ny, pcIn, pcIn, FFTW_BACKWARD, FFTW_ESTIMATE);
1684 fftw_execute (plan);
1685 fftw_destroy_plan (plan);
1687 double* pX = new double [ny];
1688 double* pYReal = new double [ny];
1689 double* pYImag = new double [ny];
1690 double* pYMag = new double [ny];
1691 for (i = 0; i < ny; i++) {
1693 pYReal[i] = pcIn[i][0] / ny;
1694 pYImag[i] = pcIn[i][1] / ny;
1695 pYMag[i] = ::sqrt (pcIn[i][0] * pcIn[i][0] + pcIn[i][1] * pcIn[i][1]);
1698 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1700 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1702 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1703 std::ostringstream os;
1704 os << "Column " << xCursor;
1705 std::string title("title ");
1707 rPlotFile.addEzsetCommand (title.c_str());
1708 rPlotFile.addEzsetCommand ("xlabel Column");
1709 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1710 rPlotFile.addEzsetCommand ("lxfrac 0");
1711 rPlotFile.addEzsetCommand ("curve 1");
1712 rPlotFile.addEzsetCommand ("color 1");
1713 rPlotFile.addEzsetCommand ("dash 1");
1714 rPlotFile.addEzsetCommand ("curve 2");
1715 rPlotFile.addEzsetCommand ("color 4");
1716 rPlotFile.addEzsetCommand ("dash 3");
1717 rPlotFile.addEzsetCommand ("curve 3");
1718 rPlotFile.addEzsetCommand ("color 0");
1719 rPlotFile.addEzsetCommand ("solid");
1720 rPlotFile.addEzsetCommand ("box");
1721 rPlotFile.addEzsetCommand ("grid");
1722 rPlotFile.setCurveSize (4, ny);
1723 rPlotFile.addColumn (0, pX);
1724 rPlotFile.addColumn (1, pYReal);
1725 rPlotFile.addColumn (2, pYImag);
1726 rPlotFile.addColumn (3, pYMag);
1727 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1728 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1729 os << " FFT Plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
1730 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1731 rPlotFile.addDescription (os.str().c_str());
1740 if (theApp->getAskDeleteNewDocs())
1741 pPlotDoc->Modify (true);
1742 pPlotDoc->getView()->getFrame()->Show(true);
1743 pPlotDoc->UpdateAllViews ();
1744 pPlotDoc->Activate();
1750 ImageFileView::OnCompareCol (wxCommandEvent& event)
1752 int xCursor, yCursor;
1753 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1754 wxMessageBox (_T("No column selected. Please use left mouse button on image to select column"),_T("Error"));
1758 std::vector<ImageFileDocument*> vecIFDoc;
1759 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1760 if (vecIFDoc.size() == 0) {
1761 wxMessageBox (_T("No compatible images for Column Comparison"), _T("Error"));
1764 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Comparison Image"), vecIFDoc, false);
1766 if (dialogGetCompare.ShowModal() == wxID_OK) {
1767 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1768 const ImageFile& rIF = GetDocument()->getImageFile();
1769 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1771 ImageFileArrayConst v1 = rIF.getArray();
1772 ImageFileArrayConst v2 = rCompareIF.getArray();
1776 if (v1 != NULL && xCursor < nx) {
1777 double* pX = new double [ny];
1778 double* pY1 = new double [ny];
1779 double* pY2 = new double [ny];
1780 for (int i = 0; i < ny; i++) {
1782 pY1[i] = v1[xCursor][i];
1783 pY2[i] = v2[xCursor][i];
1785 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1787 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1789 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1790 std::ostringstream os;
1791 os << "Column " << xCursor << " Comparison";
1792 std::string title("title ");
1794 rPlotFile.addEzsetCommand (title.c_str());
1795 rPlotFile.addEzsetCommand ("xlabel Row");
1796 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1797 rPlotFile.addEzsetCommand ("lxfrac 0");
1798 rPlotFile.addEzsetCommand ("curve 1");
1799 rPlotFile.addEzsetCommand ("color 2");
1800 rPlotFile.addEzsetCommand ("curve 2");
1801 rPlotFile.addEzsetCommand ("color 4");
1802 rPlotFile.addEzsetCommand ("dash 5");
1803 rPlotFile.addEzsetCommand ("box");
1804 rPlotFile.addEzsetCommand ("grid");
1805 rPlotFile.setCurveSize (3, ny);
1806 rPlotFile.addColumn (0, pX);
1807 rPlotFile.addColumn (1, pY1);
1808 rPlotFile.addColumn (2, pY2);
1811 for (iL = 0; iL < rIF.nLabels(); iL++) {
1812 std::ostringstream os;
1813 os << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8);
1814 os << ": " << rIF.labelGet(iL).getLabelString();
1815 rPlotFile.addDescription (os.str().c_str());
1817 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1818 std::ostringstream os;
1819 os << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8);
1821 os << rCompareIF.labelGet(iL).getLabelString();
1822 rPlotFile.addDescription (os.str().c_str());
1824 os << " Between " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str() << " and "
1825 << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
1826 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1827 rPlotFile.addDescription (os.str().c_str());
1832 if (theApp->getAskDeleteNewDocs())
1833 pPlotDoc->Modify (true);
1834 pPlotDoc->getView()->getFrame()->Show(true);
1835 pPlotDoc->UpdateAllViews ();
1836 pPlotDoc->Activate();
1842 ImageFileView::OnCompareRow (wxCommandEvent& event)
1844 int xCursor, yCursor;
1845 if (! m_pCanvas->GetCurrentCursor (xCursor, yCursor)) {
1846 wxMessageBox (_T("No column selected. Please use left mouse button on image to select column"),_T("Error"));
1850 std::vector<ImageFileDocument*> vecIFDoc;
1851 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1853 if (vecIFDoc.size() == 0) {
1854 wxMessageBox (_T("No compatible images for Row Comparison"), _T("Error"));
1858 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), _T("Get Comparison Image"), vecIFDoc, false);
1860 if (dialogGetCompare.ShowModal() == wxID_OK) {
1861 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1862 const ImageFile& rIF = GetDocument()->getImageFile();
1863 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1865 ImageFileArrayConst v1 = rIF.getArray();
1866 ImageFileArrayConst v2 = rCompareIF.getArray();
1870 if (v1 != NULL && yCursor < ny) {
1871 double* pX = new double [nx];
1872 double* pY1 = new double [nx];
1873 double* pY2 = new double [nx];
1874 for (int i = 0; i < nx; i++) {
1876 pY1[i] = v1[i][yCursor];
1877 pY2[i] = v2[i][yCursor];
1879 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1881 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1883 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1884 std::ostringstream os;
1885 os << "Row " << yCursor << " Comparison";
1886 std::string title("title ");
1888 rPlotFile.addEzsetCommand (title.c_str());
1889 rPlotFile.addEzsetCommand ("xlabel Column");
1890 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1891 rPlotFile.addEzsetCommand ("lxfrac 0");
1892 rPlotFile.addEzsetCommand ("curve 1");
1893 rPlotFile.addEzsetCommand ("color 2");
1894 rPlotFile.addEzsetCommand ("curve 2");
1895 rPlotFile.addEzsetCommand ("color 4");
1896 rPlotFile.addEzsetCommand ("dash 5");
1897 rPlotFile.addEzsetCommand ("box");
1898 rPlotFile.addEzsetCommand ("grid");
1899 rPlotFile.setCurveSize (3, nx);
1900 rPlotFile.addColumn (0, pX);
1901 rPlotFile.addColumn (1, pY1);
1902 rPlotFile.addColumn (2, pY2);
1904 for (iL = 0; iL < rIF.nLabels(); iL++) {
1905 std::ostringstream os;
1906 os << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8);
1908 os << rIF.labelGet(iL).getLabelString();
1909 rPlotFile.addDescription (os.str().c_str());
1911 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1912 std::ostringstream os;
1913 os << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8) << ": "
1914 << rCompareIF.labelGet(iL).getLabelString();
1915 rPlotFile.addDescription (os.str().c_str());
1917 os << " Between " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8) << " and "
1918 << dynamic_cast<wxFrame*>(pCompareDoc->GetFirstView()->GetFrame())->GetTitle().c_str();
1919 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1920 rPlotFile.addDescription (os.str().c_str());
1925 if (theApp->getAskDeleteNewDocs())
1926 pPlotDoc->Modify (true);
1927 pPlotDoc->getView()->getFrame()->Show(true);
1928 pPlotDoc->UpdateAllViews ();
1929 pPlotDoc->Activate();
1934 static int NUMBER_HISTOGRAM_BINS = 256;
1937 ImageFileView::OnPlotHistogram (wxCommandEvent& event)
1939 const ImageFile& rIF = GetDocument()->getImageFile();
1940 ImageFileArrayConst v = rIF.getArray();
1944 if (v != NULL && nx > 0 && ny > 0) {
1945 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
1947 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1951 double* pX = new double [NUMBER_HISTOGRAM_BINS];
1952 double* pY = new double [NUMBER_HISTOGRAM_BINS];
1954 rIF.getMinMax (dMin, dMax);
1955 double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
1957 for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
1958 pX[i] = dMin + (i + 0.5) * dBinWidth;
1961 for (int ix = 0; ix < nx; ix++)
1962 for (int iy = 0; iy < ny; iy++) {
1963 int iBin = nearest<int> ((v[ix][iy] - dMin) / dBinWidth);
1964 if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
1968 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1969 std::ostringstream os;
1971 std::string title("title ");
1973 rPlotFile.addEzsetCommand (title.c_str());
1974 rPlotFile.addEzsetCommand ("xlabel Pixel Value");
1975 rPlotFile.addEzsetCommand ("ylabel Count");
1976 rPlotFile.addEzsetCommand ("box");
1977 rPlotFile.addEzsetCommand ("grid");
1978 rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
1979 rPlotFile.addColumn (0, pX);
1980 rPlotFile.addColumn (1, pY);
1981 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++) {
1982 std::ostringstream os;
1983 os << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().mb_str(wxConvUTF8);
1984 os << ": " << rIF.labelGet(iL).getLabelString();
1985 rPlotFile.addDescription (os.str().c_str());
1987 os << " plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
1988 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
1989 rPlotFile.addDescription (os.str().c_str());
1992 if (theApp->getAskDeleteNewDocs())
1993 pPlotDoc->Modify (true);
1994 pPlotDoc->getView()->getFrame()->Show(true);
1995 pPlotDoc->UpdateAllViews ();
1996 pPlotDoc->Activate();
2003 PhantomCanvas::PhantomCanvas (PhantomFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2004 : wxScrolledWindow(frame, -1, pos, size, style), m_pView(v)
2008 PhantomCanvas::~PhantomCanvas ()
2014 PhantomCanvas::OnDraw (wxDC& dc)
2017 m_pView->OnDraw(& dc);
2021 PhantomCanvas::GetBestSize() const
2027 theApp->getMainFrame()->GetClientSize (&xSize, &ySize);
2028 xSize = maxValue<int> (xSize, ySize);
2030 ySize = xSize = (xSize / 4);
2032 xSize = ySize = static_cast<int>(ySize * .7);
2035 return wxSize (xSize, ySize);
2042 IMPLEMENT_DYNAMIC_CLASS(PhantomFileView, wxView)
2044 BEGIN_EVENT_TABLE(PhantomFileView, wxView)
2045 EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomFileView::OnProperties)
2046 EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomFileView::OnRasterize)
2047 EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomFileView::OnProjections)
2050 PhantomFileView::PhantomFileView()
2051 : wxView(), m_pFrame(NULL), m_pCanvas(NULL), m_pFileMenu(0)
2053 #if defined(DEBUG) || defined(_DEBUG)
2054 m_iDefaultNDet = 165;
2055 m_iDefaultNView = 180;
2056 m_iDefaultNSample = 1;
2058 m_iDefaultNDet = 367;
2059 m_iDefaultNView = 320;
2060 m_iDefaultNSample = 2;
2062 m_iDefaultOffsetView = 0;
2063 m_dDefaultRotation = 1;
2064 m_dDefaultFocalLength = 2;
2065 m_dDefaultCenterDetectorLength = 2;
2066 m_dDefaultViewRatio = 1;
2067 m_dDefaultScanRatio = 1;
2068 m_iDefaultGeometry = Scanner::GEOMETRY_PARALLEL;
2069 m_iDefaultTrace = Trace::TRACE_NONE;
2072 m_iDefaultRasterNX = 115;
2073 m_iDefaultRasterNY = 115;
2074 m_iDefaultRasterNSamples = 1;
2076 m_iDefaultRasterNX = 256;
2077 m_iDefaultRasterNY = 256;
2078 m_iDefaultRasterNSamples = 2;
2080 m_dDefaultRasterViewRatio = 1;
2083 PhantomFileView::~PhantomFileView()
2085 GetDocumentManager()->FileHistoryRemoveMenu (m_pFileMenu);
2086 GetDocumentManager()->ActivateView(this, FALSE);
2090 PhantomFileView::OnProperties (wxCommandEvent& event)
2092 const int idPhantom = GetDocument()->getPhantomID();
2093 const wxString& namePhantom = GetDocument()->getPhantomName();
2094 std::ostringstream os;
2095 os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n";
2096 const Phantom& rPhantom = GetDocument()->getPhantom();
2097 rPhantom.printDefinitions (os);
2099 rPhantom.print (os);
2101 *theApp->getLog() << _T(">>>>\n") << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("<<<<\n");
2102 wxMessageBox (wxConvUTF8.cMB2WX(os.str().c_str()), _T("Phantom Properties"));
2103 GetDocument()->Activate();
2108 PhantomFileView::OnProjections (wxCommandEvent& event)
2110 DialogGetProjectionParameters dialogProjection (getFrameForChild(),
2111 m_iDefaultNDet, m_iDefaultNView, m_iDefaultOffsetView, m_iDefaultNSample, m_dDefaultRotation,
2112 m_dDefaultFocalLength, m_dDefaultCenterDetectorLength, m_dDefaultViewRatio, m_dDefaultScanRatio,
2113 m_iDefaultGeometry, m_iDefaultTrace);
2114 int retVal = dialogProjection.ShowModal();
2115 if (retVal != wxID_OK)
2118 m_iDefaultNDet = dialogProjection.getNDet();
2119 m_iDefaultNView = dialogProjection.getNView();
2120 m_iDefaultOffsetView = dialogProjection.getOffsetView();
2121 m_iDefaultNSample = dialogProjection.getNSamples();
2122 m_iDefaultTrace = dialogProjection.getTrace();
2123 m_dDefaultRotation = dialogProjection.getRotAngle();
2124 m_dDefaultFocalLength = dialogProjection.getFocalLengthRatio();
2125 m_dDefaultCenterDetectorLength = dialogProjection.getCenterDetectorLengthRatio();
2126 m_dDefaultViewRatio = dialogProjection.getViewRatio();
2127 m_dDefaultScanRatio = dialogProjection.getScanRatio();
2128 wxString sGeometry (dialogProjection.getGeometry(), wxConvUTF8);
2129 m_iDefaultGeometry = Scanner::convertGeometryNameToID (sGeometry.mb_str(wxConvUTF8));
2130 double dRotationRadians = m_dDefaultRotation;
2131 m_dDefaultRotation /= TWOPI; // convert back to fraction of a circle
2133 if (m_iDefaultNDet <= 0 || m_iDefaultNView <= 0 || sGeometry == _T(""))
2136 const Phantom& rPhantom = GetDocument()->getPhantom();
2137 Scanner theScanner (rPhantom, sGeometry.mb_str(wxConvUTF8), m_iDefaultNDet, m_iDefaultNView, m_iDefaultOffsetView, m_iDefaultNSample,
2138 dRotationRadians, m_dDefaultFocalLength, m_dDefaultCenterDetectorLength, m_dDefaultViewRatio, m_dDefaultScanRatio);
2139 if (theScanner.fail()) {
2140 wxString msg = _T("Failed making scanner\n");
2141 msg += wxConvUTF8.cMB2WX(theScanner.failMessage().c_str());
2142 *theApp->getLog() << msg << _T("\n");
2143 wxMessageBox (msg, _T("Error"));
2147 std::ostringstream os;
2148 os << "Projections for " << rPhantom.name()
2149 << ": nDet=" << m_iDefaultNDet
2150 << ", nView=" << m_iDefaultNView
2151 << ", gantry offset=" << m_iDefaultOffsetView
2152 << ", nSamples=" << m_iDefaultNSample
2153 << ", RotAngle=" << m_dDefaultRotation
2154 << ", FocalLengthRatio=" << m_dDefaultFocalLength
2155 << ", CenterDetectorLengthRatio=" << m_dDefaultCenterDetectorLength
2156 << ", ViewRatio=" << m_dDefaultViewRatio
2157 << ", ScanRatio=" << m_dDefaultScanRatio
2158 << ", Geometry=" << sGeometry.c_str()
2159 << ", FanBeamAngle=" << convertRadiansToDegrees (theScanner.fanBeamAngle());
2162 Projections* pProj = NULL;
2163 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
2164 pProj = new Projections;
2165 pProj->initFromScanner (theScanner);
2167 ProjectionsDialog dialogProjections (theScanner, *pProj, rPhantom, m_iDefaultTrace, dynamic_cast<wxWindow*>(getFrameForChild()));
2168 for (int iView = 0; iView < pProj->nView(); iView++) {
2170 if (dialogProjections.isCancelled() || ! dialogProjections.projectView (iView)) {
2175 while (dialogProjections.isPaused()) {
2182 if (theApp->getUseBackgroundTasks()) {
2183 ProjectorSupervisorThread* pProjector = new ProjectorSupervisorThread
2184 (this, m_iDefaultNDet, m_iDefaultNView, m_iDefaultOffsetView,
2185 sGeometry.mb_str(wxConvUTF8), m_iDefaultNSample, dRotationRadians,
2186 m_dDefaultFocalLength, m_dDefaultCenterDetectorLength, m_dDefaultViewRatio,
2187 m_dDefaultScanRatio, wxConvUTF8.cMB2WX(os.str().c_str()));
2188 if (pProjector->Create() != wxTHREAD_NO_ERROR) {
2189 sys_error (ERR_SEVERE, "Error creating projector thread");
2193 pProjector->SetPriority(60);
2197 #endif // HAVE_WXTHREADS
2199 pProj = new Projections;
2200 pProj->initFromScanner (theScanner);
2201 wxProgressDialog dlgProgress (_T("Projection"), _T("Projection Progress"), pProj->nView() + 1, getFrameForChild(), wxPD_CAN_ABORT );
2202 for (int i = 0; i < pProj->nView(); i++) {
2203 //theScanner.collectProjections (*pProj, rPhantom, i, 1, true, m_iDefaultTrace);
2204 theScanner.collectProjections (*pProj, rPhantom, i, 1, theScanner.offsetView(), true, m_iDefaultTrace);
2205 if ((i + 1) % ITER_PER_UPDATE == 0)
2206 if (! dlgProgress.Update (i+1)) {
2214 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2215 pProj->setRemark (os.str());
2216 pProj->setCalcTime (timer.timerEnd());
2218 ProjectionFileDocument* pProjectionDoc = theApp->newProjectionDoc();
2219 if (! pProjectionDoc) {
2220 sys_error (ERR_SEVERE, "Unable to create projection document");
2223 pProjectionDoc->setProjections (pProj);
2224 if (theApp->getAskDeleteNewDocs())
2225 pProjectionDoc-> Modify(true);
2226 OnUpdate(this, NULL);
2227 pProjectionDoc->UpdateAllViews (this);
2228 pProjectionDoc->getView()->setInitialClientSize();
2229 pProjectionDoc->Activate();
2232 PhantomFileView::OnRasterize (wxCommandEvent& event)
2234 DialogGetRasterParameters dialogRaster (getFrameForChild(), m_iDefaultRasterNX, m_iDefaultRasterNY,
2235 m_iDefaultRasterNSamples, m_dDefaultRasterViewRatio);
2236 int retVal = dialogRaster.ShowModal();
2237 if (retVal != wxID_OK)
2240 m_iDefaultRasterNX = dialogRaster.getXSize();
2241 m_iDefaultRasterNY = dialogRaster.getYSize();
2242 m_iDefaultRasterNSamples = dialogRaster.getNSamples();
2243 m_dDefaultRasterViewRatio = dialogRaster.getViewRatio();
2244 if (m_iDefaultRasterNSamples < 1)
2245 m_iDefaultRasterNSamples = 1;
2246 if (m_dDefaultRasterViewRatio < 0)
2247 m_dDefaultRasterViewRatio = 0;
2248 if (m_iDefaultRasterNX <= 0 || m_iDefaultRasterNY <= 0)
2251 const Phantom& rPhantom = GetDocument()->getPhantom();
2252 std::ostringstream os;
2253 os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << m_iDefaultRasterNX << ", YSize="
2254 << m_iDefaultRasterNY << ", ViewRatio=" << m_dDefaultRasterViewRatio << ", nSamples="
2255 << m_iDefaultRasterNSamples;;
2258 if (theApp->getUseBackgroundTasks()) {
2259 RasterizerSupervisorThread* pThread = new RasterizerSupervisorThread
2260 (this, m_iDefaultRasterNX, m_iDefaultRasterNY,
2261 m_iDefaultRasterNSamples, m_dDefaultRasterViewRatio,
2262 wxConvUTF8.cMB2WX(os.str().c_str()));
2263 if (pThread->Create() != wxTHREAD_NO_ERROR) {
2264 *theApp->getLog() << _T("Error creating rasterizer thread\n");
2267 pThread->SetPriority (60);
2272 ImageFile* pImageFile = new ImageFile (m_iDefaultRasterNX, m_iDefaultRasterNY);
2274 wxProgressDialog dlgProgress (_T("Rasterize"),
2275 _T("Rasterization Progress"),
2276 pImageFile->nx() + 1,
2280 for (unsigned int i = 0; i < pImageFile->nx(); i++) {
2281 rPhantom.convertToImagefile (*pImageFile, m_dDefaultRasterViewRatio,
2282 m_iDefaultRasterNSamples, Trace::TRACE_NONE,
2284 if ((i + 1) % ITER_PER_UPDATE == 0)
2285 if (! dlgProgress.Update (i+1)) {
2291 ImageFileDocument* pRasterDoc = theApp->newImageDoc();
2293 sys_error (ERR_SEVERE, "Unable to create image file");
2296 pRasterDoc->setImageFile (pImageFile);
2297 if (theApp->getAskDeleteNewDocs())
2298 pRasterDoc->Modify (true);
2299 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2300 pImageFile->labelAdd (os.str().c_str(), timer.timerEnd());
2302 pRasterDoc->UpdateAllViews(this);
2303 pRasterDoc->getView()->setInitialClientSize();
2304 pRasterDoc->Activate();
2310 PhantomFileView::CreateCanvas (wxFrame *parent)
2312 PhantomCanvas* pCanvas = new PhantomCanvas (this, parent, wxPoint(-1,-1),
2314 pCanvas->SetBackgroundColour(*wxWHITE);
2315 pCanvas->ClearBackground();
2325 PhantomFileView::CreateChildFrame(wxDocument *doc, wxView *view)
2328 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, _T("Phantom Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
2330 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, _T("Phantom Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
2332 theApp->setIconForFrame (subframe);
2334 m_pFileMenu = new wxMenu;
2336 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
2337 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
2338 m_pFileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
2339 m_pFileMenu->Append(wxID_SAVEAS, _T("Save &As..."));
2340 m_pFileMenu->Append(wxID_CLOSE, _T("&Close"));
2342 m_pFileMenu->AppendSeparator();
2343 m_pFileMenu->Append(PHMMENU_FILE_PROPERTIES, _T("P&roperties\tCtrl-I"));
2345 m_pFileMenu->AppendSeparator();
2346 m_pFileMenu->Append(wxID_PRINT, _T("&Print..."));
2347 m_pFileMenu->Append(wxID_PRINT_SETUP, _T("Print &Setup..."));
2348 m_pFileMenu->Append(wxID_PREVIEW, _T("Print Pre&view"));
2349 m_pFileMenu->AppendSeparator();
2350 m_pFileMenu->Append(MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
2351 m_pFileMenu->AppendSeparator();
2352 m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
2353 m_pFileMenu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
2354 GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
2355 GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
2357 wxMenu *process_menu = new wxMenu;
2358 process_menu->Append(PHMMENU_PROCESS_RASTERIZE, _T("&Rasterize...\tCtrl-R"));
2359 process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, _T("&Projections...\tCtrl-J"));
2361 wxMenu *help_menu = new wxMenu;
2362 help_menu->Append(MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
2363 help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
2364 help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
2365 help_menu->Append(MAINMENU_HELP_ABOUT, _T("&About"));
2367 wxMenuBar *menu_bar = new wxMenuBar;
2369 menu_bar->Append(m_pFileMenu, _T("&File"));
2370 menu_bar->Append(process_menu, _T("&Process"));
2371 menu_bar->Append(help_menu, _T("&Help"));
2373 subframe->SetMenuBar(menu_bar);
2374 subframe->Centre(wxBOTH);
2376 wxAcceleratorEntry accelEntries[3];
2377 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('J'), PHMMENU_PROCESS_PROJECTIONS);
2378 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('R'), PHMMENU_PROCESS_RASTERIZE);
2379 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('I'), PHMMENU_FILE_PROPERTIES);
2380 wxAcceleratorTable accelTable (3, accelEntries);
2381 subframe->SetAcceleratorTable (accelTable);
2388 PhantomFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
2390 m_pFrame = CreateChildFrame(doc, this);
2392 m_pCanvas = CreateCanvas (m_pFrame);
2393 m_pFrame->SetClientSize (m_pCanvas->GetBestSize());
2394 m_pCanvas->SetClientSize (m_pCanvas->GetBestSize());
2395 m_pFrame->SetTitle (_T("PhantomFileView"));
2397 m_pFrame->Show(true);
2404 PhantomFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2407 m_pCanvas->Refresh();
2411 PhantomFileView::OnClose (bool deleteWindow)
2413 if (! GetDocument() || ! GetDocument()->Close())
2418 m_pCanvas->setView(NULL);
2421 wxString s(wxTheApp->GetAppName());
2423 m_pFrame->SetTitle(s);
2430 if (GetDocument() && GetDocument()->getBadFileOpen())
2431 ::wxYield(); // wxWindows bug workaround
2438 PhantomFileView::OnDraw (wxDC* dc)
2441 m_pCanvas->GetClientSize (&xsize, &ysize);
2442 SGPDriver driver (dc, xsize, ysize);
2444 const Phantom& rPhantom = GetDocument()->getPhantom();
2445 sgp.setColor (C_RED);
2446 rPhantom.show (sgp);
2451 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2452 : wxScrolledWindow(frame, -1, pos, size, style)
2457 ProjectionFileCanvas::~ProjectionFileCanvas ()
2463 ProjectionFileCanvas::OnDraw(wxDC& dc)
2466 m_pView->OnDraw(& dc);
2470 ProjectionFileCanvas::GetBestSize () const
2472 const int iMinX = 50;
2473 const int iMinY = 20;
2474 wxSize bestSize (iMinX,iMinY);
2477 Projections& rProj = m_pView->GetDocument()->getProjections();
2478 bestSize.Set (rProj.nDet(), rProj.nView());
2481 if (bestSize.x > 800)
2483 if (bestSize.y > 800)
2486 if (bestSize.x < iMinX)
2488 if (bestSize.y < iMinY)
2495 // ProjectionFileView
2497 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
2499 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
2500 EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
2501 EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
2502 EVT_MENU(PJMENU_RECONSTRUCT_FBP_REBIN, ProjectionFileView::OnReconstructFBPRebin)
2503 EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier)
2504 EVT_MENU(PJMENU_CONVERT_RECTANGULAR, ProjectionFileView::OnConvertRectangular)
2505 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
2506 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
2507 EVT_MENU(PJMENU_CONVERT_PARALLEL, ProjectionFileView::OnConvertParallel)
2508 EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling)
2509 EVT_MENU(PJMENU_PLOT_HISTOGRAM, ProjectionFileView::OnPlotHistogram)
2510 // EVT_MENU(PJMENU_ARTIFACT_REDUCTION, ProjectionFileView::OnArtifactReduction)
2514 ProjectionFileView::ProjectionFileView()
2515 : wxView(), m_pBitmap(0), m_pFrame(0), m_pCanvas(0), m_pFileMenu(0)
2525 m_iDefaultFilter = SignalFilter::FILTER_ABS_BANDLIMIT;
2526 m_dDefaultFilterParam = 1.;
2528 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_RFFTW;
2529 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER;
2531 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_CONVOLUTION;
2532 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT;
2534 m_iDefaultZeropad = 2;
2535 m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF;
2536 m_iDefaultInterpolation = Backprojector::INTERP_LINEAR;
2537 m_iDefaultInterpParam = 1;
2538 m_iDefaultTrace = Trace::TRACE_NONE;
2540 m_iDefaultPolarNX = 256;
2541 m_iDefaultPolarNY = 256;
2542 m_iDefaultPolarInterpolation = Projections::POLAR_INTERP_BILINEAR;
2543 m_iDefaultPolarZeropad = 2;
2546 ProjectionFileView::~ProjectionFileView()
2548 GetDocumentManager()->FileHistoryRemoveMenu (m_pFileMenu);
2549 GetDocumentManager()->ActivateView(this, FALSE);;
2553 ProjectionFileView::OnProperties (wxCommandEvent& event)
2555 const Projections& rProj = GetDocument()->getProjections();
2556 std::ostringstream os;
2557 rProj.printScanInfo(os);
2558 *theApp->getLog() << _T(">>>>\n") << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("<<<<\n");
2559 wxMessageDialog dialogMsg (getFrameForChild(), wxConvUTF8.cMB2WX(os.str().c_str()), _T("Projection File Properties"), wxOK | wxICON_INFORMATION);
2560 dialogMsg.ShowModal();
2561 GetDocument()->Activate();
2566 ProjectionFileView::OnConvertRectangular (wxCommandEvent& event)
2568 Projections& rProj = GetDocument()->getProjections();
2570 int nDet = rProj.nDet();
2571 int nView = rProj.nView();
2572 ImageFile* pIF = new ImageFile (nDet, nView);
2573 ImageFileArray v = pIF->getArray();
2574 for (int iv = 0; iv < nView; iv++) {
2575 DetectorValue* detval = rProj.getDetectorArray(iv).detValues();
2577 for (int id = 0; id < nDet; id++)
2578 v[id][iv] = detval[id];
2581 ImageFileDocument* pRectDoc = theApp->newImageDoc ();
2583 sys_error (ERR_SEVERE, "Unable to create image file");
2586 pRectDoc->setImageFile (pIF);
2587 pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2588 std::ostringstream os;
2589 os << "Convert projection file " << getFrame()->GetTitle().c_str() << " to rectangular image";
2590 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2591 pIF->labelAdd (os.str().c_str());
2592 if (theApp->getAskDeleteNewDocs())
2593 pRectDoc->Modify (true);
2594 pRectDoc->UpdateAllViews();
2595 pRectDoc->getView()->setInitialClientSize();
2596 pRectDoc->Activate();
2600 ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
2602 Projections& rProj = GetDocument()->getProjections();
2603 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), _T("Convert Polar"), m_iDefaultPolarNX, m_iDefaultPolarNY,
2604 m_iDefaultPolarInterpolation, -1, IDH_DLG_POLAR);
2605 if (dialogPolar.ShowModal() == wxID_OK) {
2606 wxProgressDialog dlgProgress (_T("Convert Polar"), _T("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
2607 wxString strInterpolation (dialogPolar.getInterpolationName(), wxConvUTF8);
2608 m_iDefaultPolarNX = dialogPolar.getXSize();
2609 m_iDefaultPolarNY = dialogPolar.getYSize();
2610 ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY);
2611 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.mb_str(wxConvUTF8));
2613 if (! rProj.convertPolar (*pIF, m_iDefaultPolarInterpolation)) {
2615 *theApp->getLog() << _T("Error converting to Polar\n");
2619 ImageFileDocument* pPolarDoc = theApp->newImageDoc();
2621 sys_error (ERR_SEVERE, "Unable to create image file");
2624 pPolarDoc->setImageFile (pIF);
2625 pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2626 std::ostringstream os;
2627 os << "Convert projection file " << getFrame()->GetTitle().c_str() << " to polar image: xSize="
2628 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2629 << strInterpolation.c_str();
2630 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2631 pIF->labelAdd (os.str().c_str());
2632 if (theApp->getAskDeleteNewDocs())
2633 pPolarDoc->Modify (true);
2634 pPolarDoc->UpdateAllViews ();
2635 pPolarDoc->getView()->setInitialClientSize();
2636 pPolarDoc->Activate();
2641 ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
2643 Projections& rProj = GetDocument()->getProjections();
2644 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), _T("Convert to FFT Polar"), m_iDefaultPolarNX, m_iDefaultPolarNY,
2645 m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad, IDH_DLG_FFT_POLAR);
2646 if (dialogPolar.ShowModal() == wxID_OK) {
2647 wxProgressDialog dlgProgress (_T("Convert FFT Polar"), _T("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
2648 wxString strInterpolation (dialogPolar.getInterpolationName(), wxConvUTF8);
2649 m_iDefaultPolarNX = dialogPolar.getXSize();
2650 m_iDefaultPolarNY = dialogPolar.getYSize();
2651 m_iDefaultPolarZeropad = dialogPolar.getZeropad();
2652 ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY);
2654 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.mb_str(wxConvUTF8));
2655 if (! rProj.convertFFTPolar (*pIF, m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad)) {
2657 *theApp->getLog() << _T("Error converting to polar\n");
2660 ImageFileDocument* pPolarDoc = theApp->newImageDoc();
2662 sys_error (ERR_SEVERE, "Unable to create image file");
2665 pPolarDoc->setImageFile (pIF);
2666 pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2667 std::ostringstream os;
2668 os << "Convert projection file " << getFrame()->GetTitle().c_str() << " to FFT polar image: xSize="
2669 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2670 << strInterpolation.c_str() << ", zeropad=" << m_iDefaultPolarZeropad;
2671 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2672 pIF->labelAdd (os.str().c_str());
2673 if (theApp->getAskDeleteNewDocs())
2674 pPolarDoc->Modify (true);
2675 pPolarDoc->UpdateAllViews (this);
2676 pPolarDoc->getView()->setInitialClientSize();
2677 pPolarDoc->Activate();
2682 ProjectionFileView::OnPlotTThetaSampling (wxCommandEvent& event)
2684 DialogGetThetaRange dlgTheta (this->getFrame(), ParallelRaysums::THETA_RANGE_UNCONSTRAINED);
2685 if (dlgTheta.ShowModal() != wxID_OK)
2688 int iThetaRange = dlgTheta.getThetaRange();
2690 Projections& rProj = GetDocument()->getProjections();
2691 ParallelRaysums parallel (&rProj, iThetaRange);
2692 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
2693 PlotFile& rPlot = pPlotDoc->getPlotFile();
2694 ParallelRaysums::CoordinateContainer& coordContainer = parallel.getCoordinates();
2695 double* pdT = new double [parallel.getNumCoordinates()];
2696 double* pdTheta = new double [parallel.getNumCoordinates()];
2698 for (int i = 0; i < parallel.getNumCoordinates(); i++) {
2699 pdT[i] = coordContainer[i]->m_dT;
2700 pdTheta[i] = coordContainer[i]->m_dTheta;
2702 rPlot.setCurveSize (2, parallel.getNumCoordinates(), true);
2703 rPlot.addEzsetCommand ("title T-Theta Sampling");
2704 rPlot.addEzsetCommand ("xlabel T");
2705 rPlot.addEzsetCommand ("ylabel Theta");
2706 rPlot.addEzsetCommand ("curve 1");
2707 if (rProj.nDet() < 50 && rProj.nView() < 50)
2708 rPlot.addEzsetCommand ("symbol 1"); // x symbol
2710 rPlot.addEzsetCommand ("symbol 6"); // point symbol
2711 rPlot.addEzsetCommand ("noline");
2712 rPlot.addColumn (0, pdT);
2713 rPlot.addColumn (1, pdTheta);
2716 if (theApp->getAskDeleteNewDocs())
2717 pPlotDoc->Modify (true);
2718 pPlotDoc->getView()->getFrame()->Show(true);
2719 pPlotDoc->UpdateAllViews ();
2720 pPlotDoc->Activate();
2725 ProjectionFileView::OnPlotHistogram (wxCommandEvent& event)
2727 Projections& rProj = GetDocument()->getProjections();
2728 int nDet = rProj.nDet();
2729 int nView = rProj.nView();
2731 if (nDet < 1 || nView < 1)
2734 PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
2736 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
2740 DetectorValue* pdDetval = rProj.getDetectorArray(0).detValues();
2741 double dMin = pdDetval[0], dMax = pdDetval[0];
2743 for (int iv = 0; iv < nView; iv++) {
2744 pdDetval = rProj.getDetectorArray(iv).detValues();
2745 for (int id = 0; id < nDet; id++) {
2746 double dV = pdDetval[id];
2754 double* pX = new double [NUMBER_HISTOGRAM_BINS];
2755 double* pY = new double [NUMBER_HISTOGRAM_BINS];
2756 double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
2758 for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
2759 pX[i] = dMin + (i + 0.5) * dBinWidth;
2762 for (int j = 0; j < nView; j++) {
2763 pdDetval = rProj.getDetectorArray(j).detValues();
2764 for (int id = 0; id < nDet; id++) {
2765 int iBin = nearest<int> ((pdDetval[id] - dMin) / dBinWidth);
2766 if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
2770 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
2771 std::ostringstream os;
2773 std::string title("title ");
2775 rPlotFile.addEzsetCommand (title.c_str());
2776 rPlotFile.addEzsetCommand ("xlabel Detector Value");
2777 rPlotFile.addEzsetCommand ("ylabel Count");
2778 rPlotFile.addEzsetCommand ("box");
2779 rPlotFile.addEzsetCommand ("grid");
2780 rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
2781 rPlotFile.addColumn (0, pX);
2782 rPlotFile.addColumn (1, pY);
2783 rPlotFile.addDescription (rProj.remark());
2784 os << " plot of " << dynamic_cast<wxFrame*>(GetDocument()->GetFirstView()->GetFrame())->GetTitle().c_str();
2785 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2786 rPlotFile.addDescription (os.str().c_str());
2789 if (theApp->getAskDeleteNewDocs())
2790 pPlotDoc->Modify (true);
2791 pPlotDoc->getView()->getFrame()->Show(true);
2792 pPlotDoc->UpdateAllViews ();
2793 pPlotDoc->Activate();
2798 ProjectionFileView::OnConvertParallel (wxCommandEvent& event)
2800 Projections& rProj = GetDocument()->getProjections();
2801 if (rProj.geometry() == Scanner::GEOMETRY_PARALLEL) {
2802 wxMessageBox (_T("Projections are already parallel"), _T("Error"));
2805 wxProgressDialog dlgProgress (_T("Convert to Parallel"), _T("Conversion Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
2806 Projections* pProjNew = rProj.interpolateToParallel();
2807 ProjectionFileDocument* pProjDocNew = theApp->newProjectionDoc();
2808 pProjDocNew->setProjections (pProjNew);
2810 if (ProjectionFileView* projView = pProjDocNew->getView()) {
2811 projView->OnUpdate (projView, NULL);
2812 if (projView->getCanvas())
2813 projView->getCanvas()->SetClientSize (pProjNew->nDet(), pProjNew->nView());
2814 if (wxFrame* pFrame = projView->getFrame()) {
2819 GetDocumentManager()->ActivateView (projView, true);
2821 if (theApp->getAskDeleteNewDocs())
2822 pProjDocNew-> Modify(true);
2823 pProjDocNew->UpdateAllViews (this);
2824 pProjDocNew->getView()->setInitialClientSize();
2825 pProjDocNew->Activate();
2829 ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
2831 Projections& rProj = GetDocument()->getProjections();
2832 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), _T("Fourier Reconstruction"), m_iDefaultPolarNX, m_iDefaultPolarNY,
2833 m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad, IDH_DLG_RECON_FOURIER);
2834 if (dialogPolar.ShowModal() == wxID_OK) {
2835 wxProgressDialog dlgProgress (_T("Reconstruction Fourier"), _T("Reconstruction Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
2836 wxString strInterpolation (dialogPolar.getInterpolationName(), wxConvUTF8);
2837 m_iDefaultPolarNX = dialogPolar.getXSize();
2838 m_iDefaultPolarNY = dialogPolar.getYSize();
2839 m_iDefaultPolarZeropad = dialogPolar.getZeropad();
2840 ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY);
2842 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.mb_str(wxConvUTF8));
2843 if (! rProj.convertFFTPolar (*pIF, m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad)) {
2845 *theApp->getLog() << _T("Error converting to polar\n");
2851 pIF->magnitude(*pIF);
2852 Fourier::shuffleFourierToNaturalOrder (*pIF);
2854 ImageFileDocument* pPolarDoc = theApp->newImageDoc();
2856 sys_error (ERR_SEVERE, "Unable to create image file");
2859 pPolarDoc->setImageFile (pIF);
2860 pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2861 std::ostringstream os;
2862 os << "Reconstruct Fourier " << getFrame()->GetTitle().mb_str(wxConvUTF8) << ": xSize="
2863 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2864 << strInterpolation.mb_str(wxConvUTF8) << ", zeropad=" << m_iDefaultPolarZeropad;
2865 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
2866 pIF->labelAdd (os.str().c_str());
2867 if (theApp->getAskDeleteNewDocs())
2868 pPolarDoc->Modify (true);
2869 pPolarDoc->UpdateAllViews ();
2870 pPolarDoc->getView()->setInitialClientSize();
2871 pPolarDoc->Activate();
2876 ProjectionFileView::OnReconstructFBPRebin (wxCommandEvent& event)
2878 Projections& rProj = GetDocument()->getProjections();
2879 doReconstructFBP (rProj, true);
2883 ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
2885 Projections& rProj = GetDocument()->getProjections();
2886 doReconstructFBP (rProj, false);
2890 ProjectionFileView::doReconstructFBP (const Projections& rProj, bool bRebinToParallel)
2892 ReconstructionROI defaultROI;
2893 defaultROI.m_dXMin = -rProj.phmLen() / 2;
2894 defaultROI.m_dXMax = defaultROI.m_dXMin + rProj.phmLen();
2895 defaultROI.m_dYMin = -rProj.phmLen() / 2;
2896 defaultROI.m_dYMax = defaultROI.m_dYMin + rProj.phmLen();
2898 DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY,
2899 m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration,
2900 m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector,
2901 m_iDefaultTrace, &defaultROI);
2903 int retVal = dialogReconstruction.ShowModal();
2904 if (retVal != wxID_OK)
2907 m_iDefaultNX = dialogReconstruction.getXSize();
2908 m_iDefaultNY = dialogReconstruction.getYSize();
2909 wxString optFilterName (dialogReconstruction.getFilterName(), wxConvUTF8);
2910 m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.mb_str(wxConvUTF8));
2911 m_dDefaultFilterParam = dialogReconstruction.getFilterParam();
2912 wxString optFilterMethodName (dialogReconstruction.getFilterMethodName(), wxConvUTF8);
2913 m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.mb_str(wxConvUTF8));
2914 m_iDefaultZeropad = dialogReconstruction.getZeropad();
2915 wxString optFilterGenerationName (dialogReconstruction.getFilterGenerationName(), wxConvUTF8);
2916 m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.mb_str(wxConvUTF8));
2917 wxString optInterpName (dialogReconstruction.getInterpName(), wxConvUTF8);
2918 m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.mb_str(wxConvUTF8));
2919 m_iDefaultInterpParam = dialogReconstruction.getInterpParam();
2920 wxString optBackprojectName (dialogReconstruction.getBackprojectName(), wxConvUTF8);
2921 m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.mb_str(wxConvUTF8));
2922 m_iDefaultTrace = dialogReconstruction.getTrace();
2923 dialogReconstruction.getROI (&defaultROI);
2925 if (m_iDefaultNX <= 0 && m_iDefaultNY <= 0)
2928 std::ostringstream os;
2929 os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.mb_str(wxConvUTF8) << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.mb_str(wxConvUTF8) << ", FilterGeneration=" << optFilterGenerationName.mb_str(wxConvUTF8) << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.mb_str(wxConvUTF8) << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.mb_str(wxConvUTF8);
2930 if (bRebinToParallel)
2931 os << "; Interpolate to Parallel";
2934 ImageFile* pImageFile = NULL;
2935 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
2936 pImageFile = new ImageFile (m_iDefaultNX, m_iDefaultNY);
2937 Reconstructor* pReconstructor = new Reconstructor (rProj, *pImageFile, optFilterName.mb_str(wxConvUTF8),
2938 m_dDefaultFilterParam, optFilterMethodName.mb_str(wxConvUTF8), m_iDefaultZeropad, optFilterGenerationName.mb_str(wxConvUTF8),
2939 optInterpName.mb_str(wxConvUTF8), m_iDefaultInterpParam, optBackprojectName.mb_str(wxConvUTF8), m_iDefaultTrace,
2940 &defaultROI, bRebinToParallel);
2942 ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstructor, rProj, *pImageFile, m_iDefaultTrace, getFrameForChild());
2943 for (int iView = 0; iView < rProj.nView(); iView++) {
2945 if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView, true)) {
2946 delete pDlgReconstruct;
2947 delete pReconstructor;
2952 while (pDlgReconstruct->isPaused()) {
2957 pReconstructor->postProcessing();
2958 delete pDlgReconstruct;
2959 delete pReconstructor;
2962 if (theApp->getUseBackgroundTasks()) {
2963 ReconstructorSupervisorThread* pReconstructor = new ReconstructorSupervisorThread
2964 (this, m_iDefaultNX, m_iDefaultNY, optFilterName.mb_str(wxConvUTF8),
2965 m_dDefaultFilterParam, optFilterMethodName.mb_str(wxConvUTF8),
2966 m_iDefaultZeropad, optFilterGenerationName.mb_str(wxConvUTF8),
2967 optInterpName.mb_str(wxConvUTF8), m_iDefaultInterpParam,
2968 optBackprojectName.mb_str(wxConvUTF8),
2969 wxConvUTF8.cMB2WX(os.str().c_str()), &defaultROI, bRebinToParallel);
2970 if (pReconstructor->Create() != wxTHREAD_NO_ERROR) {
2971 sys_error (ERR_SEVERE, "Error creating reconstructor thread");
2972 delete pReconstructor;
2975 pReconstructor->SetPriority (60);
2976 pReconstructor->Run();
2981 pImageFile = new ImageFile (m_iDefaultNX, m_iDefaultNY);
2982 wxProgressDialog dlgProgress (_T("Reconstruction"), _T("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT );
2983 Reconstructor* pReconstructor = new Reconstructor (rProj, *pImageFile, optFilterName.mb_str(wxConvUTF8),
2984 m_dDefaultFilterParam, optFilterMethodName.mb_str(wxConvUTF8), m_iDefaultZeropad, optFilterGenerationName.mb_str(wxConvUTF8),
2985 optInterpName.mb_str(wxConvUTF8), m_iDefaultInterpParam, optBackprojectName.mb_str(wxConvUTF8), m_iDefaultTrace,
2986 &defaultROI, bRebinToParallel);
2988 for (int iView = 0; iView < rProj.nView(); iView++) {
2989 pReconstructor->reconstructView (iView, 1);
2990 if ((iView + 1) % ITER_PER_UPDATE == 0)
2991 if (! dlgProgress.Update (iView + 1)) {
2992 delete pReconstructor;
2993 return; // don't make new window, thread will do this
2996 pReconstructor->postProcessing();
2997 delete pReconstructor;
3000 ImageFileDocument* pReconDoc = theApp->newImageDoc();
3002 sys_error (ERR_SEVERE, "Unable to create image file");
3005 *theApp->getLog() << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("\n");
3006 pImageFile->labelAdd (rProj.getLabel());
3007 pImageFile->labelAdd (os.str().c_str(), timerRecon.timerEnd());
3009 pReconDoc->setImageFile (pImageFile);
3010 if (theApp->getAskDeleteNewDocs())
3011 pReconDoc->Modify (true);
3012 pReconDoc->UpdateAllViews();
3013 pReconDoc->getView()->setInitialClientSize();
3014 pReconDoc->Activate();
3019 ProjectionFileView::OnArtifactReduction (wxCommandEvent& event)
3024 ProjectionFileCanvas*
3025 ProjectionFileView::CreateCanvas (wxFrame *parent)
3027 ProjectionFileCanvas* pCanvas;
3029 parent->GetClientSize(&width, &height);
3031 pCanvas = new ProjectionFileCanvas (this, parent, wxPoint(-1,-1), wxSize(width, height), 0);
3033 pCanvas->SetScrollbars(20, 20, 50, 50);
3034 pCanvas->SetBackgroundColour(*wxWHITE);
3035 pCanvas->ClearBackground();
3045 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
3048 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, _T("Projection Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
3050 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, _T("Projection Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
3052 theApp->setIconForFrame (subframe);
3054 m_pFileMenu = new wxMenu;
3056 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
3057 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
3058 m_pFileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
3059 m_pFileMenu->Append(wxID_SAVE, _T("&Save\tCtrl-S"));
3060 m_pFileMenu->Append(wxID_SAVEAS, _T("Save &As..."));
3061 m_pFileMenu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
3063 m_pFileMenu->AppendSeparator();
3064 m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, _T("P&roperties\tCtrl-I"));
3066 m_pFileMenu->AppendSeparator();
3067 m_pFileMenu->Append(wxID_PRINT, _T("&Print..."));
3068 m_pFileMenu->Append(wxID_PRINT_SETUP, _T("Print &Setup..."));
3069 m_pFileMenu->Append(wxID_PREVIEW, _T("Print Pre&view"));
3070 m_pFileMenu->AppendSeparator();
3071 m_pFileMenu->Append(MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
3072 m_pFileMenu->AppendSeparator();
3073 m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
3074 m_pFileMenu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
3075 GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
3076 GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
3078 m_pConvertMenu = new wxMenu;
3079 m_pConvertMenu->Append (PJMENU_CONVERT_RECTANGULAR, _T("&Rectangular Image"));
3080 m_pConvertMenu->Append (PJMENU_CONVERT_POLAR, _T("&Polar Image...\tCtrl-L"));
3081 m_pConvertMenu->Append (PJMENU_CONVERT_FFT_POLAR, _T("FF&T->Polar Image...\tCtrl-T"));
3082 m_pConvertMenu->AppendSeparator();
3083 m_pConvertMenu->Append (PJMENU_CONVERT_PARALLEL, _T("&Interpolate to Parallel"));
3085 // wxMenu* filter_menu = new wxMenu;
3086 // filter_menu->Append (PJMENU_ARTIFACT_REDUCTION, _T("&Artifact Reduction"));
3088 wxMenu* analyze_menu = new wxMenu;
3089 analyze_menu->Append (PJMENU_PLOT_HISTOGRAM, _T("&Plot Histogram"));
3090 analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, _T("Plot T-T&heta Sampling...\tCtrl-H"));
3092 m_pReconstructMenu = new wxMenu;
3093 m_pReconstructMenu->Append (PJMENU_RECONSTRUCT_FBP, _T("&Filtered Backprojection...\tCtrl-R"), _T("Reconstruct image using filtered backprojection"));
3094 m_pReconstructMenu->Append (PJMENU_RECONSTRUCT_FBP_REBIN, _T("Filtered &Backprojection (Rebin to Parallel)...\tCtrl-B"), _T("Reconstruct image using filtered backprojection"));
3095 m_pReconstructMenu->Append (PJMENU_RECONSTRUCT_FOURIER, _T("&Inverse Fourier...\tCtrl-E"), _T("Direct inverse Fourier"));
3097 wxMenu *help_menu = new wxMenu;
3098 help_menu->Append(MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
3099 help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
3100 help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
3101 help_menu->Append(MAINMENU_HELP_ABOUT, _T("&About"));
3103 wxMenuBar *menu_bar = new wxMenuBar;
3105 menu_bar->Append (m_pFileMenu, _T("&File"));
3106 menu_bar->Append (m_pConvertMenu, _T("&Convert"));
3107 // menu_bar->Append (filter_menu, _T("Fi<er"));
3108 menu_bar->Append (analyze_menu, _T("&Analyze"));
3109 menu_bar->Append (m_pReconstructMenu, _T("&Reconstruct"));
3110 menu_bar->Append (help_menu, _T("&Help"));
3112 subframe->SetMenuBar(menu_bar);
3113 subframe->Centre(wxBOTH);
3115 wxAcceleratorEntry accelEntries[7];
3116 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
3117 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_CONVERT_FFT_POLAR);
3118 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
3119 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('B'), PJMENU_RECONSTRUCT_FBP_REBIN);
3120 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
3121 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
3122 accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('H'), PJMENU_PLOT_TTHETA_SAMPLING);
3123 wxAcceleratorTable accelTable (7, accelEntries);
3124 subframe->SetAcceleratorTable (accelTable);
3131 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
3133 m_pFrame = CreateChildFrame(doc, this);
3135 m_pCanvas = CreateCanvas (m_pFrame);
3136 m_pFrame->SetClientSize (m_pCanvas->GetBestSize());
3137 m_pCanvas->SetClientSize (m_pCanvas->GetBestSize());
3138 m_pFrame->SetTitle (_T("ProjectionFileView"));
3140 m_pFrame->Show(true);
3147 ProjectionFileView::OnDraw (wxDC* dc)
3149 if (m_pBitmap && m_pBitmap->Ok())
3150 dc->DrawBitmap (*m_pBitmap, 0, 0, false);
3155 ProjectionFileView::setInitialClientSize ()
3157 if (m_pFrame && m_pCanvas) {
3158 wxSize bestSize = m_pCanvas->GetBestSize();
3160 m_pFrame->SetClientSize (bestSize);
3161 m_pFrame->Show (true);
3162 m_pFrame->SetFocus();
3167 ProjectionFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
3169 const Projections& rProj = GetDocument()->getProjections();
3170 const int nDet = rProj.nDet();
3171 const int nView = rProj.nView();
3172 if (rProj.geometry() == Scanner::GEOMETRY_PARALLEL) {
3173 m_pReconstructMenu->Enable (PJMENU_RECONSTRUCT_FBP_REBIN, false);
3174 m_pConvertMenu->Enable (PJMENU_CONVERT_PARALLEL, false);
3176 m_pReconstructMenu->Enable (PJMENU_RECONSTRUCT_FBP_REBIN, true);
3177 m_pConvertMenu->Enable (PJMENU_CONVERT_PARALLEL, true);
3180 if (nDet != 0 && nView != 0) {
3181 const DetectorArray& detarray = rProj.getDetectorArray(0);
3182 const DetectorValue* detval = detarray.detValues();
3183 double min = detval[0];
3184 double max = detval[0];
3185 for (int iy = 0; iy < nView; iy++) {
3186 const DetectorArray& detarray = rProj.getDetectorArray(iy);
3187 const DetectorValue* detval = detarray.detValues();
3188 for (int ix = 0; ix < nDet; ix++) {
3189 if (min > detval[ix])
3191 else if (max < detval[ix])
3196 unsigned char* imageData = new unsigned char [nDet * nView * 3];
3198 sys_error (ERR_SEVERE, "Unable to allocate memory for image display");
3201 double scale = (max - min) / 255;
3202 for (int iy2 = 0; iy2 < nView; iy2++) {
3203 const DetectorArray& detarray = rProj.getDetectorArray (iy2);
3204 const DetectorValue* detval = detarray.detValues();
3205 for (int ix = 0; ix < nDet; ix++) {
3206 int intensity = static_cast<int>(((detval[ix] - min) / scale) + 0.5);
3207 intensity = clamp(intensity, 0, 255);
3208 int baseAddr = (iy2 * nDet + ix) * 3;
3209 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
3212 wxImage image (nDet, nView, imageData, true);
3217 m_pBitmap = new wxBitmap (image);
3221 m_pCanvas->SetScrollbars(20, 20, nDet/20, nView/20);
3222 m_pCanvas->SetBackgroundColour(*wxWHITE);
3225 m_pCanvas->Refresh();
3229 ProjectionFileView::OnClose (bool deleteWindow)
3231 //GetDocumentManager()->ActivateView (this, false);
3232 if (! GetDocument() || ! GetDocument()->Close())
3237 m_pCanvas->setView(NULL);
3240 wxString s(wxTheApp->GetAppName());
3242 m_pFrame->SetTitle(s);
3249 if (GetDocument() && GetDocument()->getBadFileOpen())
3250 ::wxYield(); // wxWindows bug workaround
3259 PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
3260 : wxScrolledWindow(frame, -1, pos, size, style), m_pView(v)
3264 PlotFileCanvas::~PlotFileCanvas ()
3269 PlotFileCanvas::GetBestSize() const
3271 return wxSize (500, 300);
3276 PlotFileCanvas::OnDraw(wxDC& dc)
3279 m_pView->OnDraw(& dc);
3285 IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
3287 BEGIN_EVENT_TABLE(PlotFileView, wxView)
3288 EVT_MENU(PLOTMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
3289 EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax)
3290 EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto)
3291 EVT_MENU(PLOTMENU_VIEW_SCALE_FULL, PlotFileView::OnScaleFull)
3294 PlotFileView::PlotFileView()
3295 : wxView(), m_pFrame(0), m_pCanvas(0), m_pEZPlot(0), m_pFileMenu(0),
3296 m_bMinSpecified(false), m_bMaxSpecified(false)
3300 PlotFileView::~PlotFileView()
3305 GetDocumentManager()->FileHistoryRemoveMenu (m_pFileMenu);
3306 GetDocumentManager()->ActivateView(this, FALSE);
3310 PlotFileView::OnProperties (wxCommandEvent& event)
3312 const PlotFile& rPlot = GetDocument()->getPlotFile();
3313 std::ostringstream os;
3314 os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";
3315 rPlot.printHeadersBrief (os);
3316 *theApp->getLog() << _T(">>>>\n") << wxConvUTF8.cMB2WX(os.str().c_str()) << _T("<<<<<\n");
3317 wxMessageDialog dialogMsg (getFrameForChild(), wxConvUTF8.cMB2WX(os.str().c_str()), _T("Plot File Properties"),
3318 wxOK | wxICON_INFORMATION);
3319 dialogMsg.ShowModal();
3320 GetDocument()->Activate();
3325 PlotFileView::OnScaleAuto (wxCommandEvent& event)
3327 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
3328 double min, max, mean, mode, median, stddev;
3329 rPlotFile.statistics (1, min, max, mean, mode, median, stddev);
3330 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
3331 int iRetVal = dialogAutoScale.ShowModal();
3332 if (iRetVal == wxID_OK) {
3333 m_bMinSpecified = true;
3334 m_bMaxSpecified = true;
3336 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
3339 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
3340 OnUpdate (this, NULL);
3343 GetDocument()->Activate();
3347 PlotFileView::OnScaleMinMax (wxCommandEvent& event)
3349 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
3353 if (! m_bMinSpecified || ! m_bMaxSpecified) {
3354 if (! rPlotFile.getMinMax (1, min, max)) {
3355 *theApp->getLog() << _T("Error: unable to find Min/Max\n");
3360 if (m_bMinSpecified)
3362 if (m_bMaxSpecified)
3365 DialogGetMinMax dialogMinMax (getFrameForChild(), _T("Set Y-axis Minimum & Maximum"), min, max);
3366 int retVal = dialogMinMax.ShowModal();
3367 if (retVal == wxID_OK) {
3368 m_bMinSpecified = true;
3369 m_bMaxSpecified = true;
3370 m_dMinPixel = dialogMinMax.getMinimum();
3371 m_dMaxPixel = dialogMinMax.getMaximum();
3372 OnUpdate (this, NULL);
3374 GetDocument()->Activate();
3378 PlotFileView::OnScaleFull (wxCommandEvent& event)
3380 if (m_bMinSpecified || m_bMaxSpecified) {
3381 m_bMinSpecified = false;
3382 m_bMaxSpecified = false;
3383 OnUpdate (this, NULL);
3385 GetDocument()->Activate();
3390 PlotFileView::CreateCanvas (wxFrame* parent)
3392 PlotFileCanvas* pCanvas;
3394 pCanvas = new PlotFileCanvas (this, parent, wxPoint(-1,-1), wxSize(-1,-1), 0);
3395 pCanvas->SetBackgroundColour(*wxWHITE);
3396 pCanvas->ClearBackground();
3406 PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
3409 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, _T("Plot Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
3411 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, _T("Plot Frame"), wxPoint(-1,-1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE);
3413 theApp->setIconForFrame (subframe);
3415 m_pFileMenu = new wxMenu;
3417 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
3418 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
3419 m_pFileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
3420 m_pFileMenu->Append(wxID_SAVE, _T("&Save\tCtrl-S"));
3421 m_pFileMenu->Append(wxID_SAVEAS, _T("Save &As..."));
3422 m_pFileMenu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
3424 m_pFileMenu->AppendSeparator();
3425 m_pFileMenu->Append(PLOTMENU_FILE_PROPERTIES, _T("P&roperties\tCtrl-I"));
3427 m_pFileMenu->AppendSeparator();
3428 m_pFileMenu->Append(wxID_PRINT, _T("&Print..."));
3429 m_pFileMenu->Append(wxID_PRINT_SETUP, _T("Print &Setup..."));
3430 m_pFileMenu->Append(wxID_PREVIEW, _T("Print Pre&view"));
3431 m_pFileMenu->AppendSeparator();
3432 m_pFileMenu->Append(MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
3433 m_pFileMenu->AppendSeparator();
3434 m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
3435 m_pFileMenu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
3436 GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
3437 GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
3439 wxMenu *view_menu = new wxMenu;
3440 view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, _T("Display Scale &Set...\tCtrl-E"));
3441 view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, _T("Display Scale &Auto...\tCtrl-A"));
3442 view_menu->Append(PLOTMENU_VIEW_SCALE_FULL, _T("Display &Full Scale\tCtrl-U"));
3444 wxMenu *help_menu = new wxMenu;
3445 help_menu->Append(MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
3446 help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
3447 help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
3448 help_menu->Append(MAINMENU_HELP_ABOUT, _T("&About"));
3450 wxMenuBar *menu_bar = new wxMenuBar;
3452 menu_bar->Append(m_pFileMenu, _T("&File"));
3453 menu_bar->Append(view_menu, _T("&View"));
3454 menu_bar->Append(help_menu, _T("&Help"));
3456 subframe->SetMenuBar(menu_bar);
3457 subframe->Centre(wxBOTH);
3459 wxAcceleratorEntry accelEntries[4];
3460 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('E'), PLOTMENU_VIEW_SCALE_MINMAX);
3461 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('A'), PLOTMENU_VIEW_SCALE_AUTO);
3462 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('U'), PLOTMENU_VIEW_SCALE_FULL);
3463 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('I'), PLOTMENU_FILE_PROPERTIES);
3464 wxAcceleratorTable accelTable (4, accelEntries);
3465 subframe->SetAcceleratorTable (accelTable);
3472 PlotFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
3474 m_bMinSpecified = false;
3475 m_bMaxSpecified = false;
3476 m_dAutoScaleFactor = 1.;
3478 m_pFrame = CreateChildFrame(doc, this);
3480 m_pCanvas = CreateCanvas (m_pFrame);
3481 m_pFrame->SetClientSize (m_pCanvas->GetBestSize());
3482 m_pCanvas->SetClientSize (m_pCanvas->GetBestSize());
3483 m_pFrame->SetTitle (_T("Plot File"));
3485 m_pFrame->Show(true);
3492 PlotFileView::setInitialClientSize ()
3494 if (m_pFrame && m_pCanvas) {
3495 wxSize bestSize = m_pCanvas->GetBestSize();
3497 m_pFrame->SetClientSize (bestSize);
3498 m_pFrame->Show (true);
3499 m_pFrame->SetFocus();
3505 PlotFileView::OnDraw (wxDC* dc)
3507 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
3508 const int iNColumns = rPlotFile.getNumColumns();
3509 const int iNRecords = rPlotFile.getNumRecords();
3511 if (iNColumns > 0 && iNRecords > 0) {
3513 m_pCanvas->GetClientSize (&xsize, &ysize);
3514 SGPDriver driver (dc, xsize, ysize);
3517 m_pEZPlot->plot (&sgp);
3523 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
3525 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
3526 const int iNColumns = rPlotFile.getNumColumns();
3527 const int iNRecords = rPlotFile.getNumRecords();
3528 const bool bScatterPlot = rPlotFile.getIsScatterPlot();
3530 if (iNColumns > 0 && iNRecords > 0) {
3533 m_pEZPlot = new EZPlot;
3535 for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)
3536 m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));
3538 if (m_bMinSpecified) {
3539 std::ostringstream os;
3540 os << "ymin " << m_dMinPixel;
3541 m_pEZPlot->ezset (os.str());
3544 if (m_bMaxSpecified) {
3545 std::ostringstream os;
3546 os << "ymax " << m_dMaxPixel;
3547 m_pEZPlot->ezset (os.str());
3550 m_pEZPlot->ezset("box");
3551 m_pEZPlot->ezset("grid");
3553 double* pdX = new double [iNRecords];
3554 double* pdY = new double [iNRecords];
3555 if (! bScatterPlot) {
3556 rPlotFile.getColumn (0, pdX);
3558 for (int iCol = 1; iCol < iNColumns; iCol++) {
3559 rPlotFile.getColumn (iCol, pdY);
3560 m_pEZPlot->addCurve (pdX, pdY, iNRecords);
3563 rPlotFile.getColumn (0, pdX);
3564 rPlotFile.getColumn (1, pdY);
3565 m_pEZPlot->addCurve (pdX, pdY, iNRecords);
3572 m_pCanvas->Refresh();
3576 PlotFileView::OnClose (bool deleteWindow)
3578 if (! GetDocument() || ! GetDocument()->Close())
3583 m_pCanvas->setView (NULL);
3586 wxString s(wxTheApp->GetAppName());
3588 m_pFrame->SetTitle(s);
3594 if (GetDocument() && GetDocument()->getBadFileOpen())
3595 ::wxYield(); // wxWindows bug workaround
3602 ////////////////////////////////////////////////////////////////
3605 IMPLEMENT_DYNAMIC_CLASS(TextFileView, wxView)
3607 TextFileView::~TextFileView()
3609 GetDocumentManager()->FileHistoryRemoveMenu (m_pFileMenu);
3610 GetDocumentManager()->ActivateView(this, FALSE);;
3613 bool TextFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
3615 m_pFrame = CreateChildFrame(doc, this);
3616 SetFrame (m_pFrame);
3619 m_pFrame->GetClientSize(&width, &height);
3620 m_pFrame->SetTitle(_T("TextFile"));
3621 m_pCanvas = new TextFileCanvas (this, m_pFrame, wxPoint(-1,-1), wxSize(width, height), wxTE_MULTILINE | wxTE_READONLY);
3622 m_pFrame->SetTitle(_T("Log"));
3624 m_pFrame->Show (true);
3630 // Handled by wxTextWindow
3631 void TextFileView::OnDraw(wxDC *WXUNUSED(dc) )
3635 void TextFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
3640 TextFileView::OnClose (bool deleteWindow)
3642 if (! theApp->getMainFrame()->getShuttingDown())
3646 //GetDocumentManager()->ActivateView (this, false);
3647 if (! GetDocument() || ! GetDocument()->Close())
3654 if (GetDocument() && GetDocument()->getBadFileOpen())
3655 ::wxYield(); // wxWindows bug workaround
3666 TextFileView::CreateChildFrame (wxDocument *doc, wxView *view)
3669 wxDocMDIChildFrame* subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, _T("TextFile Frame"), wxPoint(-1, -1), wxSize(-1,-1), wxDEFAULT_FRAME_STYLE, _T("Log"));
3671 wxDocChildFrame* subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, _T("TextFile Frame"), wxPoint(-1, -1), wxSize(300, 150), wxDEFAULT_FRAME_STYLE, _T("Log"));
3673 theApp->setIconForFrame (subframe);
3675 m_pFileMenu = new wxMenu;
3677 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
3678 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
3679 m_pFileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
3680 m_pFileMenu->Append(wxID_SAVE, _T("&Save\tCtrl-S"));
3681 m_pFileMenu->Append(wxID_SAVEAS, _T("Save &As..."));
3682 // m_pFileMenu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
3684 m_pFileMenu->AppendSeparator();
3685 m_pFileMenu->Append(wxID_PRINT, _T("&Print..."));
3686 m_pFileMenu->Append(wxID_PRINT_SETUP, _T("Print &Setup..."));
3687 m_pFileMenu->Append(wxID_PREVIEW, _T("Print Pre&view"));
3688 m_pFileMenu->AppendSeparator();
3689 m_pFileMenu->Append(MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
3690 m_pFileMenu->AppendSeparator();
3691 m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
3692 m_pFileMenu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
3693 GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
3694 GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
3696 wxMenu *help_menu = new wxMenu;
3697 help_menu->Append(MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
3698 help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
3699 help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
3700 help_menu->Append(MAINMENU_HELP_ABOUT, _T("&About"));
3702 wxMenuBar *menu_bar = new wxMenuBar;
3704 menu_bar->Append(m_pFileMenu, _T("&File"));
3705 menu_bar->Append(help_menu, _T("&Help"));
3707 subframe->SetMenuBar(menu_bar);
3708 subframe->Centre(wxBOTH);
3714 // Define a constructor for my text subwindow
3715 TextFileCanvas::TextFileCanvas (TextFileView* v, wxFrame* frame, const wxPoint& pos, const wxSize& size, long style)
3716 : wxTextCtrl (frame, -1, _T(""), pos, size, style), m_pView(v)
3720 TextFileCanvas::~TextFileCanvas ()
3726 TextFileCanvas::GetBestSize() const
3729 theApp->getMainFrame()->GetClientSize (&xSize, &ySize);
3730 xSize = maxValue<int> (xSize, ySize);
3732 ySize = xSize = (xSize / 4);
3736 return wxSize (xSize, ySize);