r334: *** empty log message ***
[ctsim.git] / src / views.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          view.cpp
5 **   Purpose:       View & Canvas routines for CTSim program
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  July 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id: views.cpp,v 1.46 2001/01/02 08:18:33 kevin Exp $
13 **
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.
17 **
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.
22 **
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 ******************************************************************************/
27
28 // For compilers that support precompilation, includes "wx/wx.h".
29 #include "wx/wxprec.h"
30
31 #ifdef __BORLANDC__
32 #pragma hdrstop
33 #endif
34
35 #ifndef WX_PRECOMP
36 #include "wx/wx.h"
37 #endif
38
39 #if !wxUSE_DOC_VIEW_ARCHITECTURE
40 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
41 #endif
42
43 #include "wx/image.h"
44 #include "wx/progdlg.h"
45
46 #include "ct.h"
47 #include "ctsim.h"
48 #include "docs.h"
49 #include "views.h"
50 #include "dialogs.h"
51 #include "dlgprojections.h"
52 #include "dlgreconstruct.h"
53 #include "backprojectors.h"
54 #include "reconstruct.h"
55 #include "timer.h"
56 \r
57 #if defined(MSVC) || HAVE_SSTREAM\r
58 #include <sstream>\r
59 #else\r
60 #include <sstream_subst>\r
61 #endif\r
62 \r
63
64 // ImageFileCanvas
65
66 BEGIN_EVENT_TABLE(ImageFileCanvas, wxScrolledWindow)
67 EVT_MOUSE_EVENTS(ImageFileCanvas::OnMouseEvent)
68 END_EVENT_TABLE()
69
70
71 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
72 : wxScrolledWindow(frame, -1, pos, size, style)
73 {
74   m_pView = v;\r
75   m_xCursor = -1;\r
76   m_yCursor = -1;
77 }
78
79 void 
80 ImageFileCanvas::OnDraw(wxDC& dc)
81 {
82   if (m_pView)
83     m_pView->OnDraw(& dc);
84 }\r
85 \r
86 void \r
87 ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y)\r
88 {\r
89   const ImageFile& rIF = m_pView->GetDocument()->getImageFile();\r
90   int nx = rIF.nx();\r
91   int ny = rIF.ny();\r
92   \r
93   int yPt = ny - y - 1;\r
94   dc.SetLogicalFunction (wxINVERT);\r
95   dc.SetPen (*wxGREEN_PEN);\r
96   dc.DrawLine (0, yPt, nx, yPt);\r
97   dc.DrawLine (x, 0, x, ny);\r
98   dc.SetLogicalFunction (wxCOPY);\r
99 }\r
100 \r
101 bool\r
102 ImageFileCanvas::GetCurrentCursor (int& x, int& y)\r
103 {\r
104   x = m_xCursor;\r
105   y = m_yCursor;\r
106   \r
107   if (m_xCursor >= 0 && m_yCursor >= 0)\r
108     return true;\r
109   else\r
110     return false;\r
111 }
112 \r
113 void 
114 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
115 {
116   if (! m_pView)
117     return;
118   
119   wxClientDC dc(this);
120   PrepareDC(dc);
121   
122   wxPoint pt(event.GetLogicalPosition(dc));
123   \r
124   const ImageFile& rIF = m_pView->GetDocument()->getImageFile();\r
125   ImageFileArrayConst v = rIF.getArray();\r
126   int nx = rIF.nx();\r
127   int ny = rIF.ny();\r
128   const int yPt = ny - 1 - pt.y;\r
129   if (event.RightIsDown()) {\r
130     if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {\r
131       std::ostringstream os;\r
132       os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt];\r
133       if (rIF.isComplex()) {\r
134         double dImag = rIF.getImaginaryArray()[pt.x][yPt];\r
135         if (dImag < 0)\r
136           os << " - " << -dImag;\r
137         else\r
138           os << " + " << dImag;\r
139         os << "i\n";\r
140       } else\r
141         os << "\n";\r
142       *theApp->getLog() << os.str().c_str();\r
143     } else\r
144       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";\r
145   }\r
146   else if (event.LeftIsDown() || event.LeftUp() || event.RightUp()) {\r
147     if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {\r
148       if (m_xCursor >= 0 && m_yCursor >= 0) {\r
149         DrawRubberBandCursor (dc, m_xCursor, m_yCursor);\r
150       }\r
151       DrawRubberBandCursor (dc, pt.x, yPt);\r
152       m_xCursor = pt.x;\r
153       m_yCursor = yPt;\r
154     } else\r
155       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";\r
156   }\r
157   if (event.LeftUp()) {\r
158     std::ostringstream os;\r
159     os << "Selected column " << pt.x << " , row " << yPt << "\n";\r
160     *theApp->getLog() << os.str().c_str();\r
161   }\r
162 }
163
164 // ImageFileView
165
166 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
167
168 BEGIN_EVENT_TABLE(ImageFileView, wxView)\r
169 EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
170 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
171 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
172 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)\r
173 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)\r
174 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)\r
175 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)\r
176 EVT_MENU(IFMENU_FILTER_INVERTVALUES, ImageFileView::OnInvertValues)\r
177 EVT_MENU(IFMENU_FILTER_SQUARE, ImageFileView::OnSquare)\r
178 EVT_MENU(IFMENU_FILTER_SQRT, ImageFileView::OnSquareRoot)\r
179 EVT_MENU(IFMENU_FILTER_LOG, ImageFileView::OnLog)\r
180 EVT_MENU(IFMENU_FILTER_EXP, ImageFileView::OnExp)\r
181 EVT_MENU(IFMENU_FILTER_FOURIER, ImageFileView::OnFourier)\r
182 EVT_MENU(IFMENU_FILTER_INVERSE_FOURIER, ImageFileView::OnInverseFourier)\r
183 EVT_MENU(IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)\r
184 EVT_MENU(IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)\r
185 EVT_MENU(IFMENU_IMAGE_ADD, ImageFileView::OnAdd)\r
186 EVT_MENU(IFMENU_IMAGE_SUBTRACT, ImageFileView::OnSubtract)\r
187 EVT_MENU(IFMENU_IMAGE_MULTIPLY, ImageFileView::OnMultiply)\r
188 EVT_MENU(IFMENU_IMAGE_DIVIDE, ImageFileView::OnDivide)\r
189 EVT_MENU(IFMENU_IMAGE_SCALESIZE, ImageFileView::OnScaleSize)\r
190 #ifdef HAVE_FFTW\r
191 EVT_MENU(IFMENU_FILTER_FFT, ImageFileView::OnFFT)\r
192 EVT_MENU(IFMENU_FILTER_IFFT, ImageFileView::OnIFFT)\r
193 #endif\r
194 EVT_MENU(IFMENU_FILTER_MAGNITUDE, ImageFileView::OnMagnitude)\r
195 EVT_MENU(IFMENU_FILTER_PHASE, ImageFileView::OnPhase)\r
196 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)\r
197 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)\r
198 END_EVENT_TABLE()
199
200 ImageFileView::ImageFileView(void) 
201 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
202 {\r
203   m_iDefaultExportFormatID = ImageFile::FORMAT_PNG;\r
204 }
205
206 ImageFileView::~ImageFileView(void)
207 {
208 }
209
210 void
211 ImageFileView::OnProperties (wxCommandEvent& event)
212 {
213   const ImageFile& rIF = GetDocument()->getImageFile();
214   if (rIF.nx() == 0 || rIF.ny() == 0)
215     *theApp->getLog() << "Properties: empty imagefile\n";
216   else {
217     const std::string& rFilename = rIF.getFilename();
218     std::ostringstream os;
219     double min, max, mean, mode, median, stddev;\r
220     rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);\r
221     os << "Filename: " << rFilename << "\n";\r
222     os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";\r
223     os << "Data type: ";\r
224     if (rIF.isComplex())\r
225       os << "Complex\n";\r
226     else\r
227       os << "Real\n";\r
228     os << "\nMinimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
229     if (rIF.isComplex()) {\r
230       rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);\r
231       os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";\r
232     }\r
233     if (rIF.nLabels() > 0) {\r
234       os << "\n";\r
235       rIF.printLabelsBrief (os);\r
236     }\r
237     *theApp->getLog() << os.str().c_str();
238     wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
239     dialogMsg.ShowModal();
240   }
241 }
242
243 void 
244 ImageFileView::OnScaleAuto (wxCommandEvent& event)
245 {
246   const ImageFile& rIF = GetDocument()->getImageFile();
247   double min, max, mean, mode, median, stddev;\r
248   rIF.statistics(min, max, mean, mode, median, stddev);\r
249   DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor);
250   int iRetVal = dialogAutoScale.ShowModal();
251   if (iRetVal == wxID_OK) {
252     m_bMinSpecified = true;
253     m_bMaxSpecified = true;
254     double dMin, dMax;\r
255     if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
256       m_dMinPixel = dMin;
257       m_dMaxPixel = dMax;
258       m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
259       OnUpdate (this, NULL);\r
260     }
261   }
262 }
263
264 void 
265 ImageFileView::OnScaleMinMax (wxCommandEvent& event)
266 {
267   const ImageFile& rIF = GetDocument()->getImageFile();
268   double min, max;
269   if (! m_bMinSpecified && ! m_bMaxSpecified)
270     rIF.getMinMax (min, max);
271   
272   if (m_bMinSpecified)
273     min = m_dMinPixel;
274   if (m_bMaxSpecified)
275     max = m_dMaxPixel;
276   
277   DialogGetMinMax dialogMinMax (m_frame, "Set Image Minimum & Maximum", min, max);
278   int retVal = dialogMinMax.ShowModal();
279   if (retVal == wxID_OK) {
280     m_bMinSpecified = true;
281     m_bMaxSpecified = true;
282     m_dMinPixel = dialogMinMax.getMinimum();
283     m_dMaxPixel = dialogMinMax.getMaximum();
284     OnUpdate (this, NULL);
285   }
286 }
287 \r
288 void\r
289 ImageFileView::OnCompare (wxCommandEvent& event)\r
290 {\r
291   std::vector<ImageFileDocument*> vecIF;\r
292   theApp->getCompatibleImages (GetDocument(), vecIF);\r
293   \r
294   if (vecIF.size() == 0) {\r
295     wxMessageBox("There are no compatible image files open for comparision", "No comparison images");\r
296   } else {\r
297     DialogGetComparisonImage dialogGetCompare(m_frame, "Get Comparison Image", vecIF, true);\r
298     \r
299     if (dialogGetCompare.ShowModal() == wxID_OK) {\r
300       const ImageFile& rIF = GetDocument()->getImageFile();\r
301       ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();\r
302       const ImageFile& rCompareIF = pCompareDoc->getImageFile();\r
303       std::ostringstream os;\r
304       double min, max, mean, mode, median, stddev;\r
305       rIF.statistics (min, max, mean, mode, median, stddev);\r
306       os << rIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
307       rCompareIF.statistics (min, max, mean, mode, median, stddev);\r
308       os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
309       os << "\n";\r
310       double d, r, e;\r
311       rIF.comparativeStatistics (rCompareIF, d, r, e);\r
312       os << "Comparative Statistics: d=" << d << ", r=" << r << ", e=" << e << "\n";\r
313       *theApp->getLog() << os.str().c_str();\r
314       if (dialogGetCompare.getMakeDifferenceImage()) {\r
315         ImageFileDocument* pDifferenceDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
316         if (! pDifferenceDoc) {\r
317           sys_error (ERR_SEVERE, "Unable to create image file");\r
318           return;\r
319         }\r
320         ImageFile& differenceImage = pDifferenceDoc->getImageFile();\r
321         \r
322         differenceImage.setArraySize (rIF.nx(), rIF.ny());\r
323         if (! rIF.subtractImages (rCompareIF, differenceImage)) {\r
324           pDifferenceDoc->DeleteAllViews();\r
325           return;\r
326         }\r
327         \r
328         wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
329         differenceImage.labelsCopy (rIF, s.c_str());\r
330         s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
331         differenceImage.labelsCopy (rCompareIF, s.c_str());\r
332         std::ostringstream osLabel;\r
333         osLabel << "Compare image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() \r
334           << " and " << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": "\r
335           << os.str().c_str();\r
336         differenceImage.labelAdd (os.str().c_str());\r
337         if (theApp->getSetModifyNewDocs())\r
338           pDifferenceDoc->Modify(true);\r
339         pDifferenceDoc->UpdateAllViews(this);\r
340         pDifferenceDoc->GetFirstView()->OnUpdate (this, NULL);\r
341       }\r
342       wxMessageBox(os.str().c_str(), "Image Comparison");\r
343     }\r
344   }\r
345 }
346
347 void\r
348 ImageFileView::OnInvertValues (wxCommandEvent& event)\r
349 {\r
350   ImageFile& rIF = GetDocument()->getImageFile();\r
351   rIF.invertPixelValues (rIF);\r
352   rIF.labelAdd ("Invert Pixel Values");\r
353   if (theApp->getSetModifyNewDocs())\r
354     GetDocument()->Modify(TRUE);\r
355   GetDocument()->UpdateAllViews(this);\r
356 }\r
357 \r
358 void\r
359 ImageFileView::OnSquare (wxCommandEvent& event)\r
360 {\r
361   ImageFile& rIF = GetDocument()->getImageFile();\r
362   rIF.square (rIF);\r
363   rIF.labelAdd ("Square Pixel Values");\r
364   if (theApp->getSetModifyNewDocs())\r
365     GetDocument()->Modify(TRUE);\r
366   GetDocument()->UpdateAllViews(this);\r
367 }\r
368 \r
369 void\r
370 ImageFileView::OnSquareRoot (wxCommandEvent& event)\r
371 {\r
372   ImageFile& rIF = GetDocument()->getImageFile();\r
373   rIF.sqrt (rIF);\r
374   rIF.labelAdd ("Square-root Pixel Values");\r
375   if (theApp->getSetModifyNewDocs())\r
376     GetDocument()->Modify(TRUE);\r
377   GetDocument()->UpdateAllViews(this);\r
378 }\r
379 \r
380 void\r
381 ImageFileView::OnLog (wxCommandEvent& event)\r
382 {\r
383   ImageFile& rIF = GetDocument()->getImageFile();\r
384   rIF.log (rIF);\r
385   rIF.labelAdd ("Logrithm base-e Pixel Values");\r
386   if (theApp->getSetModifyNewDocs())\r
387     GetDocument()->Modify(TRUE);\r
388   GetDocument()->UpdateAllViews(this);\r
389 }\r
390 \r
391 void\r
392 ImageFileView::OnExp (wxCommandEvent& event)\r
393 {\r
394   ImageFile& rIF = GetDocument()->getImageFile();\r
395   rIF.exp (rIF);\r
396   rIF.labelAdd ("Exponent base-e Pixel Values");\r
397   if (theApp->getSetModifyNewDocs())\r
398     GetDocument()->Modify(TRUE);\r
399   GetDocument()->UpdateAllViews(this);\r
400 }\r
401 \r
402 void\r
403 ImageFileView::OnAdd (wxCommandEvent& event)\r
404 {\r
405   std::vector<ImageFileDocument*> vecIF;\r
406   theApp->getCompatibleImages (GetDocument(), vecIF);\r
407   \r
408   if (vecIF.size() == 0) {\r
409     wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
410   } else {\r
411     DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Add", vecIF, false);\r
412     \r
413     if (dialogGetCompare.ShowModal() == wxID_OK) {\r
414       ImageFile& rIF = GetDocument()->getImageFile();\r
415       ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
416       const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
417       ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
418         if (! pNewDoc) {\r
419           sys_error (ERR_SEVERE, "Unable to create image file");\r
420           return;\r
421         }\r
422       ImageFile& newImage = pNewDoc->getImageFile();  \r
423       newImage.setArraySize (rIF.nx(), rIF.ny());\r
424       rIF.addImages (rRHSIF, newImage);\r
425       std::ostringstream os;\r
426       os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
427         << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
428       wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
429       newImage.labelsCopy (rIF, s.c_str());\r
430       s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
431       newImage.labelsCopy (rRHSIF, s.c_str());\r
432       newImage.labelAdd (os.str().c_str());\r
433       *theApp->getLog() << os.str().c_str() << "\n";\r
434       if (theApp->getSetModifyNewDocs())\r
435         pNewDoc->Modify(TRUE);\r
436       pNewDoc->UpdateAllViews(this);\r
437       pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
438     }\r
439   }\r
440 }\r
441 \r
442 void\r
443 ImageFileView::OnSubtract (wxCommandEvent& event)\r
444 {\r
445   std::vector<ImageFileDocument*> vecIF;\r
446   theApp->getCompatibleImages (GetDocument(), vecIF);\r
447   \r
448   if (vecIF.size() == 0) {\r
449     wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
450   } else {\r
451     DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Subtract", vecIF, false);\r
452     \r
453     if (dialogGetCompare.ShowModal() == wxID_OK) {\r
454       ImageFile& rIF = GetDocument()->getImageFile();\r
455       ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
456       const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
457       ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
458         if (! pNewDoc) {\r
459           sys_error (ERR_SEVERE, "Unable to create image file");\r
460           return;\r
461         }\r
462       ImageFile& newImage = pNewDoc->getImageFile();  \r
463       newImage.setArraySize (rIF.nx(), rIF.ny());\r
464       rIF.subtractImages (rRHSIF, newImage);\r
465       std::ostringstream os;\r
466       os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
467         << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
468       wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
469       newImage.labelsCopy (rIF, s.c_str());\r
470       s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
471       newImage.labelsCopy (rRHSIF, s.c_str());\r
472       newImage.labelAdd (os.str().c_str());\r
473       *theApp->getLog() << os.str().c_str() << "\n";\r
474       if (theApp->getSetModifyNewDocs())\r
475         pNewDoc->Modify(TRUE);\r
476       pNewDoc->UpdateAllViews(this);\r
477       pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
478     }\r
479   }\r
480 }\r
481 \r
482 void\r
483 ImageFileView::OnMultiply (wxCommandEvent& event)\r
484 {\r
485   std::vector<ImageFileDocument*> vecIF;\r
486   theApp->getCompatibleImages (GetDocument(), vecIF);\r
487   \r
488   if (vecIF.size() == 0) {\r
489     wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
490   } else {\r
491     DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Multiply", vecIF, false);\r
492     \r
493     if (dialogGetCompare.ShowModal() == wxID_OK) {\r
494       ImageFile& rIF = GetDocument()->getImageFile();\r
495       ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
496       const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
497       ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
498         if (! pNewDoc) {\r
499           sys_error (ERR_SEVERE, "Unable to create image file");\r
500           return;\r
501         }\r
502       ImageFile& newImage = pNewDoc->getImageFile();  \r
503       newImage.setArraySize (rIF.nx(), rIF.ny());\r
504       rIF.multiplyImages (rRHSIF, newImage);\r
505       std::ostringstream os;\r
506       os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
507         << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
508       wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
509       newImage.labelsCopy (rIF, s.c_str());\r
510       s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
511       newImage.labelsCopy (rRHSIF, s.c_str());\r
512       newImage.labelAdd (os.str().c_str());\r
513       *theApp->getLog() << os.str().c_str() << "\n";\r
514       if (theApp->getSetModifyNewDocs())\r
515         pNewDoc->Modify(TRUE);\r
516       pNewDoc->UpdateAllViews(this);\r
517       pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
518     }\r
519   }\r
520 }\r
521 \r
522 void\r
523 ImageFileView::OnDivide (wxCommandEvent& event)\r
524 {\r
525   std::vector<ImageFileDocument*> vecIF;\r
526   theApp->getCompatibleImages (GetDocument(), vecIF);\r
527   \r
528   if (vecIF.size() == 0) {\r
529     wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
530   } else {\r
531     DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Divide", vecIF, false);\r
532     \r
533     if (dialogGetCompare.ShowModal() == wxID_OK) {\r
534       ImageFile& rIF = GetDocument()->getImageFile();\r
535       ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
536       const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
537       ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
538         if (! pNewDoc) {\r
539           sys_error (ERR_SEVERE, "Unable to create image file");\r
540           return;\r
541         }\r
542       ImageFile& newImage = pNewDoc->getImageFile();  \r
543       newImage.setArraySize (rIF.nx(), rIF.ny());\r
544       rIF.divideImages (rRHSIF, newImage);\r
545       std::ostringstream os;\r
546       os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " by " \r
547         << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
548       wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
549       newImage.labelsCopy (rIF, s.c_str());\r
550       s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
551       newImage.labelsCopy (rRHSIF, s.c_str());\r
552       newImage.labelAdd (os.str().c_str());\r
553       *theApp->getLog() << os.str().c_str() << "\n";\r
554       if (theApp->getSetModifyNewDocs())\r
555         pNewDoc->Modify(TRUE);\r
556       pNewDoc->UpdateAllViews(this);\r
557       pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
558     }\r
559   }\r
560 }\r
561 \r
562 \r
563 #ifdef HAVE_FFTW\r
564 void\r
565 ImageFileView::OnFFT (wxCommandEvent& event)\r
566 {\r
567   ImageFile& rIF = GetDocument()->getImageFile();\r
568   wxProgressDialog dlgProgress (wxString("FFT"), wxString("FFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
569   rIF.fft (rIF);\r
570   rIF.labelAdd ("FFT Image");\r
571   m_bMinSpecified = false;\r
572   m_bMaxSpecified = false;\r
573   if (theApp->getSetModifyNewDocs())\r
574     GetDocument()->Modify(TRUE);\r
575   GetDocument()->UpdateAllViews(this);\r
576 }\r
577 \r
578 void\r
579 ImageFileView::OnIFFT (wxCommandEvent& event)\r
580 {\r
581   ImageFile& rIF = GetDocument()->getImageFile();\r
582   wxProgressDialog dlgProgress (wxString("IFFT"), wxString("IFFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
583   rIF.ifft (rIF);\r
584   rIF.labelAdd ("IFFT Image");\r
585   m_bMinSpecified = false;\r
586   m_bMaxSpecified = false;\r
587   if (theApp->getSetModifyNewDocs())\r
588     GetDocument()->Modify(TRUE);\r
589   GetDocument()->UpdateAllViews(this);\r
590 }\r
591 #endif\r
592 \r
593 void\r
594 ImageFileView::OnFourier (wxCommandEvent& event)\r
595 {\r
596   ImageFile& rIF = GetDocument()->getImageFile();\r
597   wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
598   rIF.fourier (rIF);\r
599   rIF.labelAdd ("Fourier Image");\r
600   m_bMinSpecified = false;\r
601   m_bMaxSpecified = false;\r
602   if (theApp->getSetModifyNewDocs())\r
603     GetDocument()->Modify(TRUE);\r
604   GetDocument()->UpdateAllViews(this);\r
605 }\r
606 void\r
607 ImageFileView::OnInverseFourier (wxCommandEvent& event)\r
608 {\r
609   ImageFile& rIF = GetDocument()->getImageFile();\r
610   wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
611   rIF.inverseFourier (rIF);\r
612   rIF.labelAdd ("Inverse Fourier Image");\r
613   m_bMinSpecified = false;\r
614   m_bMaxSpecified = false;\r
615   if (theApp->getSetModifyNewDocs())\r
616     GetDocument()->Modify(TRUE);\r
617   GetDocument()->UpdateAllViews(this);\r
618 }\r
619 \r
620 void\r
621 ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)\r
622 {\r
623   ImageFile& rIF = GetDocument()->getImageFile();\r
624   Fourier::shuffleNaturalToFourierOrder (rIF);\r
625   rIF.labelAdd ("Shuffle Natural To Fourier Order");\r
626   m_bMinSpecified = false;\r
627   m_bMaxSpecified = false;\r
628   if (theApp->getSetModifyNewDocs())\r
629     GetDocument()->Modify(TRUE);\r
630   GetDocument()->UpdateAllViews(this);\r
631 }\r
632 \r
633 void\r
634 ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)\r
635 {\r
636   ImageFile& rIF = GetDocument()->getImageFile();\r
637   Fourier::shuffleFourierToNaturalOrder (rIF);\r
638   rIF.labelAdd ("Shuffle Fourier To Natural Order");\r
639   m_bMinSpecified = false;\r
640   m_bMaxSpecified = false;\r
641   if (theApp->getSetModifyNewDocs())\r
642     GetDocument()->Modify(TRUE);\r
643   GetDocument()->UpdateAllViews(this);\r
644 }\r
645 \r
646 void\r
647 ImageFileView::OnMagnitude (wxCommandEvent& event)\r
648 {\r
649   ImageFile& rIF = GetDocument()->getImageFile();\r
650   if (rIF.isComplex()) {\r
651     rIF.magnitude (rIF);\r
652     rIF.labelAdd ("Magnitude of complex-image");\r
653   m_bMinSpecified = false;\r
654   m_bMaxSpecified = false;\r
655   if (theApp->getSetModifyNewDocs())\r
656     GetDocument()->Modify(TRUE);\r
657   GetDocument()->UpdateAllViews(this);\r
658   }\r
659 }\r
660 \r
661 void\r
662 ImageFileView::OnPhase (wxCommandEvent& event)\r
663 {\r
664   ImageFile& rIF = GetDocument()->getImageFile();\r
665   if (rIF.isComplex()) {\r
666     rIF.phase (rIF);\r
667     rIF.labelAdd ("Phase of complex-image");\r
668   m_bMinSpecified = false;\r
669   m_bMaxSpecified = false;\r
670   if (theApp->getSetModifyNewDocs())\r
671     GetDocument()->Modify(TRUE);\r
672   GetDocument()->UpdateAllViews(this);\r
673   }\r
674 }\r
675 \r
676 \r
677 ImageFileCanvas* 
678 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
679 {
680   ImageFileCanvas* pCanvas;
681   int width, height;
682   parent->GetClientSize(&width, &height);
683   
684   pCanvas = new ImageFileCanvas (dynamic_cast<ImageFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
685   
686   pCanvas->SetScrollbars(20, 20, 50, 50);
687   pCanvas->SetBackgroundColour(*wxWHITE);
688   pCanvas->Clear();
689   
690   return pCanvas;
691 }
692
693 wxFrame*
694 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
695 {
696   wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
697   
698   wxMenu *file_menu = new wxMenu;
699   
700   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");\r
701   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
702   file_menu->Append(wxID_OPEN, "&Open...");
703   file_menu->Append(wxID_SAVE, "&Save");
704   file_menu->Append(wxID_SAVEAS, "Save &As...");
705   file_menu->Append(wxID_CLOSE, "&Close");
706   
707   file_menu->AppendSeparator();\r
708   file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
709   file_menu->Append(IFMENU_FILE_EXPORT, "&Export...");\r
710   
711   file_menu->AppendSeparator();
712   file_menu->Append(wxID_PRINT, "&Print...");
713   file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
714   file_menu->Append(wxID_PREVIEW, "Print Pre&view");
715   
716   wxMenu *view_menu = new wxMenu;
717   view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");
718   view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");
719   \r
720   wxMenu* filter_menu = new wxMenu;\r
721   filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");\r
722   filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");\r
723   filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");\r
724   filter_menu->Append (IFMENU_FILTER_LOG, "&Log");\r
725   filter_menu->Append (IFMENU_FILTER_EXP, "&Exp");\r
726   filter_menu->AppendSeparator();\r
727 #ifdef HAVE_FFTW\r
728   filter_menu->Append (IFMENU_FILTER_FFT, "&FFT");\r
729   filter_menu->Append (IFMENU_FILTER_IFFT, "&IFFT");\r
730   filter_menu->Append (IFMENU_FILTER_FOURIER, "F&ourier");\r
731   filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "Inverse Fo&urier");\r
732 #else\r
733   filter_menu->Append (IFMENU_FILTER_FOURIER, "&Fourier");\r
734   filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "&Inverse Fourier");\r
735 #endif\r
736   filter_menu->Append (IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order");\r
737   filter_menu->Append (IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order");\r
738   filter_menu->Append (IFMENU_FILTER_MAGNITUDE, "&Magnitude");\r
739   filter_menu->Append (IFMENU_FILTER_PHASE, "&Phase");\r
740   \r
741   wxMenu* image_menu = new wxMenu;\r
742   filter_menu->AppendSeparator();\r
743   image_menu->Append (IFMENU_IMAGE_ADD, "&Add...");\r
744   image_menu->Append (IFMENU_IMAGE_SUBTRACT, "&Subtract...");\r
745   image_menu->Append (IFMENU_IMAGE_MULTIPLY, "&Multiply...");\r
746   image_menu->Append (IFMENU_IMAGE_DIVIDE, "&Divide...");\r
747   image_menu->AppendSeparator();\r
748   image_menu->Append (IFMENU_IMAGE_SCALESIZE, "S&cale Size...");\r
749 \r
750   wxMenu *plot_menu = new wxMenu;\r
751   plot_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");\r
752   plot_menu->Append (IFMENU_PLOT_COL, "Plot &Column");\r
753   
754   wxMenu *compare_menu = new wxMenu;\r
755   compare_menu->Append (IFMENU_COMPARE_IMAGES, "Compare &Images...");\r
756   compare_menu->Append (IFMENU_COMPARE_ROW, "Compare &Row");\r
757   compare_menu->Append (IFMENU_COMPARE_COL, "Compare &Column");\r
758   \r
759   wxMenu *help_menu = new wxMenu;
760   help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
761   
762   wxMenuBar *menu_bar = new wxMenuBar;
763   
764   menu_bar->Append(file_menu, "&File");
765   menu_bar->Append(view_menu, "&View");\r
766   menu_bar->Append(image_menu, "&Image");\r
767   menu_bar->Append(filter_menu, "Fi&lter");\r
768   menu_bar->Append(plot_menu, "P&lot");\r
769   menu_bar->Append(compare_menu, "&Compare");
770   menu_bar->Append(help_menu, "&Help");
771   
772   subframe->SetMenuBar(menu_bar);
773   
774   subframe->Centre(wxBOTH);
775   
776   return subframe;
777 }
778
779
780 bool 
781 ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
782 {
783   m_frame = CreateChildFrame(doc, this);
784   SetFrame (m_frame);
785   
786   m_bMinSpecified = false;
787   m_bMaxSpecified = false;
788   m_dAutoScaleFactor = 1.;
789   
790   int width, height;
791   m_frame->GetClientSize (&width, &height);
792   m_frame->SetTitle("ImageFileView");
793   m_canvas = CreateCanvas (this, m_frame);
794   
795   int x, y;  // X requires a forced resize
796   m_frame->GetSize(&x, &y);
797   m_frame->SetSize(-1, -1, x, y);
798   m_frame->SetFocus();\r
799   m_frame->Show(true);
800   Activate(true);
801   
802   return true;
803 }
804
805 void 
806 ImageFileView::OnDraw (wxDC* dc)
807 {
808   if (m_bitmap.Ok())
809     dc->DrawBitmap(m_bitmap, 0, 0, false);
810   \r
811   int xCursor, yCursor;\r
812   if (m_canvas->GetCurrentCursor (xCursor, yCursor))\r
813     m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor);\r
814 }
815
816
817 void 
818 ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
819 {
820   const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
821   ImageFileArrayConst v = rIF.getArray();
822   int nx = rIF.nx();
823   int ny = rIF.ny();
824   if (v != NULL && nx != 0 && ny != 0) {
825     if (! m_bMinSpecified || ! m_bMaxSpecified) {
826       double min, max;
827       rIF.getMinMax (min, max);
828       if (! m_bMinSpecified)
829         m_dMinPixel = min;
830       if (! m_bMaxSpecified)
831         m_dMaxPixel = max;
832     }
833     double scaleWidth = m_dMaxPixel - m_dMinPixel;
834     
835     unsigned char* imageData = new unsigned char [nx * ny * 3];
836     for (int ix = 0; ix < nx; ix++) {
837       for (int iy = 0; iy < ny; iy++) {
838         double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
839         int intensity = static_cast<int>(scaleValue + 0.5);
840         intensity = clamp (intensity, 0, 255);
841         int baseAddr = ((ny - 1 - iy) * nx + ix) * 3;
842         imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
843       }
844     }
845     wxImage image (nx, ny, imageData, true);
846     m_bitmap = image.ConvertToBitmap();
847     delete imageData;
848     int xSize = nx;
849     int ySize = ny;
850     xSize = clamp (xSize, 0, 800);
851     ySize = clamp (ySize, 0, 800);
852     m_frame->SetClientSize (xSize, ySize);
853     m_canvas->SetScrollbars(20, 20, nx/20, ny/20);
854     m_canvas->SetBackgroundColour(*wxWHITE);\r
855   } 
856   
857   if (m_canvas)
858     m_canvas->Refresh();
859 }
860
861 bool 
862 ImageFileView::OnClose (bool deleteWindow)
863 {
864   if (!GetDocument()->Close())
865     return false;
866   
867   m_canvas->Clear();
868   m_canvas->m_pView = NULL;
869   m_canvas = NULL;
870   wxString s(theApp->GetAppName());
871   if (m_frame)
872     m_frame->SetTitle(s);
873   SetFrame(NULL);
874   
875   Activate(false);
876   
877   if (deleteWindow) {
878     delete m_frame;
879     return true;
880   }
881   return true;
882 }
883 \r
884 void\r
885 ImageFileView::OnExport (wxCommandEvent& event)\r
886 {\r
887   ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
888   ImageFileArrayConst v = rIF.getArray();\r
889   int nx = rIF.nx();\r
890   int ny = rIF.ny();\r
891   if (v != NULL && nx != 0 && ny != 0) {\r
892     if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
893       double min, max;\r
894       rIF.getMinMax (min, max);\r
895       if (! m_bMinSpecified)\r
896         m_dMinPixel = min;\r
897       if (! m_bMaxSpecified)\r
898         m_dMaxPixel = max;\r
899     }\r
900 \r
901     DialogExportParameters dialogExport (m_frame, m_iDefaultExportFormatID);\r
902     if (dialogExport.ShowModal() == wxID_OK) {\r
903       wxString strFormatName (dialogExport.getFormatName ());\r
904       m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str());\r
905 \r
906       wxString strExt;\r
907       wxString strWildcard;\r
908       if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) {\r
909         strExt = ".pgm";\r
910         strWildcard = "PGM Files (*.pgm)|*.pgm";\r
911       }\r
912 #ifdef HAVE_PNG\r
913       else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) {\r
914         strExt = ".png";\r
915         strWildcard = "PNG Files (*.png)|*.png";\r
916       }\r
917 #endif\r
918 \r
919       const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""), \r
920         wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);\r
921       if (strFilename) {\r
922         rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel);\r
923         *theApp->getLog() << "Exported file " << strFilename << "\n";\r
924       }\r
925     }\r
926   }\r
927 }\r
928 \r
929 void\r
930 ImageFileView::OnScaleSize (wxCommandEvent& event)\r
931 {\r
932   ImageFile& rIF = GetDocument()->getImageFile();\r
933   unsigned int iOldNX = rIF.nx();\r
934   unsigned int iOldNY = rIF.ny();\r
935 \r
936   DialogGetXYSize dialogGetXYSize (m_frame, "Set New X & Y Dimensions", iOldNX, iOldNY);\r
937   if (dialogGetXYSize.ShowModal() == wxID_OK) {\r
938     unsigned int iNewNX = dialogGetXYSize.getXSize();\r
939     unsigned int iNewNY = dialogGetXYSize.getYSize();\r
940     std::ostringstream os;\r
941     os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";\r
942     ImageFileDocument* pScaledDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
943     if (! pScaledDoc) {\r
944       sys_error (ERR_SEVERE, "Unable to create image file");\r
945       return;\r
946     }\r
947     ImageFile& rScaledIF = pScaledDoc->getImageFile();\r
948     rScaledIF.setArraySize (iNewNX, iNewNY);\r
949     rScaledIF.labelAdd (os.str().c_str());\r
950     rIF.scaleImage (rScaledIF);\r
951     *theApp->getLog() << os.str().c_str() << "\n";\r
952     if (theApp->getSetModifyNewDocs())\r
953       pScaledDoc->Modify(TRUE);\r
954     pScaledDoc->UpdateAllViews (this);\r
955     pScaledDoc->GetFirstView()->OnUpdate (this, NULL);\r
956   }\r
957 }\r
958 \r
959 void\r
960 ImageFileView::OnPlotRow (wxCommandEvent& event)\r
961 {\r
962   int xCursor, yCursor;\r
963   if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
964     wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");\r
965     return;\r
966   }\r
967   \r
968   const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
969   ImageFileArrayConst v = rIF.getArray();\r
970   int nx = rIF.nx();\r
971   int ny = rIF.ny();\r
972   \r
973   if (v != NULL && yCursor < ny) {\r
974     double* pX = new double [nx];\r
975     double* pY = new double [nx];\r
976     for (int i = 0; i < nx; i++) {\r
977       pX[i] = i;\r
978       pY[i] = v[i][yCursor];\r
979     }\r
980     PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
981     if (! pPlotDoc) {\r
982       sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
983     } else {\r
984       PlotFile& rPlotFile = pPlotDoc->getPlotFile();\r
985       std::ostringstream os;\r
986       os << "Row " << yCursor;\r
987       std::string title("title ");\r
988       title += os.str();\r
989       rPlotFile.addEzsetCommand (title.c_str());\r
990       rPlotFile.addEzsetCommand ("xlabel Column");\r
991       rPlotFile.addEzsetCommand ("ylabel Pixel Value");\r
992       rPlotFile.addEzsetCommand ("lxfrac 0");\r
993       rPlotFile.addEzsetCommand ("box");\r
994       rPlotFile.addEzsetCommand ("grid");\r
995       rPlotFile.setCurveSize (2, nx);\r
996       rPlotFile.addColumn (0, pX);\r
997       rPlotFile.addColumn (1, pY);\r
998     }\r
999     delete pX;\r
1000     delete pY;\r
1001     if (theApp->getSetModifyNewDocs())\r
1002       pPlotDoc->Modify(true);\r
1003     pPlotDoc->UpdateAllViews();\r
1004   }\r
1005 }\r
1006
1007 void\r
1008 ImageFileView::OnPlotCol (wxCommandEvent& event)\r
1009 {\r
1010   int xCursor, yCursor;\r
1011   if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
1012     wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");\r
1013     return;\r
1014   }\r
1015   \r
1016   const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
1017   ImageFileArrayConst v = rIF.getArray();\r
1018   int nx = rIF.nx();\r
1019   int ny = rIF.ny();\r
1020   \r
1021   if (v != NULL && xCursor < nx) {\r
1022     double* pX = new double [ny];\r
1023     double* pY = new double [ny];\r
1024     for (int i = 0; i < ny; i++) {\r
1025       pX[i] = i;\r
1026       pY[i] = v[xCursor][i];\r
1027     }\r
1028     PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
1029     if (! pPlotDoc) {\r
1030       sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
1031     } else {\r
1032       PlotFile& rPlotFile = pPlotDoc->getPlotFile();\r
1033       std::ostringstream os;\r
1034       os << "Column " << xCursor;\r
1035       std::string title("title ");\r
1036       title += os.str();\r
1037       rPlotFile.addEzsetCommand (title.c_str());\r
1038       rPlotFile.addEzsetCommand ("xlabel Row");\r
1039       rPlotFile.addEzsetCommand ("ylabel Pixel Value");\r
1040       rPlotFile.addEzsetCommand ("lxfrac 0");\r
1041       rPlotFile.addEzsetCommand ("box");\r
1042       rPlotFile.addEzsetCommand ("grid");\r
1043       rPlotFile.setCurveSize (2, nx);\r
1044       rPlotFile.addColumn (0, pX);\r
1045       rPlotFile.addColumn (1, pY);\r
1046     }\r
1047     delete pX;\r
1048     delete pY;\r
1049     if (theApp->getSetModifyNewDocs())\r
1050       pPlotDoc->Modify(true);\r
1051     pPlotDoc->UpdateAllViews();\r
1052   }\r
1053 }\r
1054 \r
1055 void\r
1056 ImageFileView::OnCompareCol (wxCommandEvent& event)\r
1057 {\r
1058   int xCursor, yCursor;\r
1059   if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
1060     wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");\r
1061     return;\r
1062   }\r
1063   \r
1064   std::vector<ImageFileDocument*> vecIFDoc;\r
1065   theApp->getCompatibleImages (GetDocument(), vecIFDoc);\r
1066   if (vecIFDoc.size() == 0) {\r
1067     wxMessageBox ("No compatible images for Column Comparison", "Error");\r
1068     return;\r
1069   }\r
1070   DialogGetComparisonImage dialogGetCompare (m_frame, "Get Comparison Image", vecIFDoc, false);\r
1071   \r
1072   if (dialogGetCompare.ShowModal() == wxID_OK) {\r
1073     ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();\r
1074     const ImageFile& rIF = GetDocument()->getImageFile();\r
1075     const ImageFile& rCompareIF = pCompareDoc->getImageFile();\r
1076     \r
1077     ImageFileArrayConst v1 = rIF.getArray();\r
1078     ImageFileArrayConst v2 = rCompareIF.getArray();\r
1079     int nx = rIF.nx();\r
1080     int ny = rIF.ny();\r
1081     \r
1082     if (v1 != NULL && xCursor < nx) {\r
1083       double* pX = new double [ny];\r
1084       double* pY1 = new double [ny];\r
1085       double* pY2 = new double [ny];\r
1086       for (int i = 0; i < ny; i++) {\r
1087         pX[i] = i;\r
1088         pY1[i] = v1[xCursor][i];\r
1089         pY2[i] = v2[xCursor][i];\r
1090       }\r
1091       PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
1092       if (! pPlotDoc) {\r
1093         sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
1094       } else {\r
1095         PlotFile& rPlotFile = pPlotDoc->getPlotFile();\r
1096         std::ostringstream os;\r
1097         os << "Column " << xCursor << " Comparison";\r
1098         std::string title("title ");\r
1099         title += os.str();\r
1100         rPlotFile.addEzsetCommand (title.c_str());\r
1101         rPlotFile.addEzsetCommand ("xlabel Row");\r
1102         rPlotFile.addEzsetCommand ("ylabel Pixel Value");\r
1103         rPlotFile.addEzsetCommand ("lxfrac 0");\r
1104         rPlotFile.addEzsetCommand ("curve 1");\r
1105         rPlotFile.addEzsetCommand ("color 2");\r
1106         rPlotFile.addEzsetCommand ("curve 2");\r
1107         rPlotFile.addEzsetCommand ("color 4");\r
1108         rPlotFile.addEzsetCommand ("dash 5");\r
1109         rPlotFile.addEzsetCommand ("box");\r
1110         rPlotFile.addEzsetCommand ("grid");\r
1111         rPlotFile.setCurveSize (3, nx);\r
1112         rPlotFile.addColumn (0, pX);\r
1113         rPlotFile.addColumn (1, pY1);\r
1114         rPlotFile.addColumn (2, pY2);\r
1115       }\r
1116       delete pX;\r
1117       delete pY1;\r
1118       delete pY2;\r
1119       if (theApp->getSetModifyNewDocs())\r
1120         pPlotDoc->Modify(true);\r
1121       pPlotDoc->UpdateAllViews();\r
1122     }\r
1123   }\r
1124 }\r
1125
1126 void\r
1127 ImageFileView::OnCompareRow (wxCommandEvent& event)\r
1128 {\r
1129   int xCursor, yCursor;\r
1130   if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
1131     wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");\r
1132     return;\r
1133   }\r
1134   \r
1135   std::vector<ImageFileDocument*> vecIFDoc;\r
1136   theApp->getCompatibleImages (GetDocument(), vecIFDoc);\r
1137   \r
1138   if (vecIFDoc.size() == 0) {\r
1139     wxMessageBox ("No compatible images for Row Comparison", "Error");\r
1140     return;\r
1141   }\r
1142   \r
1143   DialogGetComparisonImage dialogGetCompare (m_frame, "Get Comparison Image", vecIFDoc, false);\r
1144   \r
1145   if (dialogGetCompare.ShowModal() == wxID_OK) {\r
1146     ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();\r
1147     const ImageFile& rIF = GetDocument()->getImageFile();\r
1148     const ImageFile& rCompareIF = pCompareDoc->getImageFile();\r
1149     \r
1150     ImageFileArrayConst v1 = rIF.getArray();\r
1151     ImageFileArrayConst v2 = rCompareIF.getArray();\r
1152     int nx = rIF.nx();\r
1153     int ny = rIF.ny();\r
1154     \r
1155     if (v1 != NULL && yCursor < ny) {\r
1156       double* pX = new double [nx];\r
1157       double* pY1 = new double [nx];\r
1158       double* pY2 = new double [nx];\r
1159       for (int i = 0; i < nx; i++) {\r
1160         pX[i] = i;\r
1161         pY1[i] = v1[i][yCursor];\r
1162         pY2[i] = v2[i][yCursor];\r
1163       }\r
1164       PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
1165       if (! pPlotDoc) {\r
1166         sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
1167       } else {\r
1168         PlotFile& rPlotFile = pPlotDoc->getPlotFile();\r
1169         std::ostringstream os;\r
1170         os << "Row " << yCursor << " Comparison";\r
1171         std::string title("title ");\r
1172         title += os.str();\r
1173         rPlotFile.addEzsetCommand (title.c_str());\r
1174         rPlotFile.addEzsetCommand ("xlabel Column");\r
1175         rPlotFile.addEzsetCommand ("ylabel Pixel Value");\r
1176         rPlotFile.addEzsetCommand ("lxfrac 0");\r
1177         rPlotFile.addEzsetCommand ("curve 1");\r
1178         rPlotFile.addEzsetCommand ("color 2");\r
1179         rPlotFile.addEzsetCommand ("curve 2");\r
1180         rPlotFile.addEzsetCommand ("color 4");\r
1181         rPlotFile.addEzsetCommand ("dash 5");\r
1182         rPlotFile.addEzsetCommand ("box");\r
1183         rPlotFile.addEzsetCommand ("grid");\r
1184         rPlotFile.setCurveSize (3, ny);\r
1185         rPlotFile.addColumn (0, pX);\r
1186         rPlotFile.addColumn (1, pY1);\r
1187         rPlotFile.addColumn (2, pY2);\r
1188       }\r
1189       delete pX;\r
1190       delete pY1;\r
1191       delete pY2;\r
1192       if (theApp->getSetModifyNewDocs())\r
1193         pPlotDoc->Modify(true);\r
1194       pPlotDoc->UpdateAllViews();\r
1195     }\r
1196   }\r
1197 }\r
1198 \r
1199 \r
1200 // PhantomCanvas
1201
1202 PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1203 : wxScrolledWindow(frame, -1, pos, size, style)
1204 {
1205   m_pView = v;
1206 }
1207
1208 void 
1209 PhantomCanvas::OnDraw (wxDC& dc)
1210 {
1211   if (m_pView)
1212     m_pView->OnDraw(& dc);
1213 }
1214
1215
1216 // PhantomView
1217
1218 IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView)
1219
1220 BEGIN_EVENT_TABLE(PhantomView, wxView)
1221 EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomView::OnProperties)
1222 EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomView::OnRasterize)
1223 EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomView::OnProjections)
1224 END_EVENT_TABLE()
1225
1226 PhantomView::PhantomView(void) 
1227 : wxView(), m_canvas(NULL), m_frame(NULL)
1228 {
1229   m_iDefaultNDet = 367;
1230   m_iDefaultNView = 320;
1231   m_iDefaultNSample = 2;
1232   m_dDefaultRotation = 2;
1233   m_dDefaultFocalLength = 2;
1234   m_dDefaultFieldOfView = 1;
1235   m_iDefaultGeometry = Scanner::GEOMETRY_PARALLEL;
1236   m_iDefaultTrace = Trace::TRACE_NONE;
1237 }
1238
1239 PhantomView::~PhantomView(void)
1240 {
1241 }
1242
1243 void
1244 PhantomView::OnProperties (wxCommandEvent& event)
1245 {
1246   const int idPhantom = GetDocument()->getPhantomID();
1247   const wxString& namePhantom = GetDocument()->getPhantomName();
1248   std::ostringstream os;
1249   os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n";\r
1250   const Phantom& rPhantom = GetDocument()->getPhantom();\r
1251   rPhantom.printDefinitions (os);
1252 #if DEBUG
1253   rPhantom.print (os);
1254 #endif
1255   *theApp->getLog() << os.str().c_str() << "\n";\r
1256   wxMessageBox (os.str().c_str(), "Phantom Properties");\r
1257 }
1258
1259
1260 void
1261 PhantomView::OnProjections (wxCommandEvent& event)
1262 {
1263   DialogGetProjectionParameters dialogProjection (m_frame, m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView, m_iDefaultGeometry, m_iDefaultTrace);
1264   int retVal = dialogProjection.ShowModal();
1265   if (retVal == wxID_OK) {
1266     m_iDefaultNDet = dialogProjection.getNDet();
1267     m_iDefaultNView = dialogProjection.getNView();
1268     m_iDefaultNSample = dialogProjection.getNSamples();
1269     m_iDefaultTrace = dialogProjection.getTrace();
1270     m_dDefaultRotation = dialogProjection.getRotAngle();
1271     m_dDefaultFocalLength = dialogProjection.getFocalLengthRatio();
1272     m_dDefaultFieldOfView = dialogProjection.getFieldOfViewRatio();
1273     wxString sGeometry = dialogProjection.getGeometry();
1274     m_iDefaultGeometry = Scanner::convertGeometryNameToID (sGeometry.c_str());
1275     
1276     if (m_iDefaultNDet > 0 && m_iDefaultNView > 0 && sGeometry != "") {
1277       const Phantom& rPhantom = GetDocument()->getPhantom();
1278       ProjectionFileDocument* pProjectionDoc = dynamic_cast<ProjectionFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT));\r
1279       if (! pProjectionDoc) {\r
1280         sys_error (ERR_SEVERE, "Unable to create projection document");\r
1281         return;\r
1282       }
1283       Projections& rProj = pProjectionDoc->getProjections();
1284       Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView);
1285       if (theScanner.fail()) {
1286         *theApp->getLog() << "Failed making scanner: " << theScanner.failMessage().c_str() << "\n";
1287         return;
1288       }
1289       rProj.initFromScanner (theScanner);
1290       m_dDefaultRotation /= PI;  // convert back to PI units
1291       
1292       Timer timer;\r
1293       if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
1294         ProjectionsDialog dialogProjections (theScanner, rProj, rPhantom, m_iDefaultTrace, dynamic_cast<wxWindow*>(m_frame));
1295         for (int iView = 0; iView < rProj.nView(); iView++) {
1296           ::wxYield();
1297           ::wxYield();
1298           if (dialogProjections.isCancelled() || ! dialogProjections.projectView (iView)) {
1299             pProjectionDoc->DeleteAllViews();
1300             return;
1301           }
1302           ::wxYield();
1303           ::wxYield();
1304           while (dialogProjections.isPaused()) {
1305             ::wxYield();
1306             ::wxUsleep(50);
1307           }
1308         }
1309       } else {
1310         wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), rProj.nView() + 1, m_frame, wxPD_CAN_ABORT);\r
1311         for (int i = 0; i < rProj.nView(); i++) {
1312           theScanner.collectProjections (rProj, rPhantom, i, 1, true, m_iDefaultTrace);
1313           if (! dlgProgress.Update (i+1)) {
1314             pProjectionDoc->DeleteAllViews();
1315             return;
1316           }
1317         }
1318       }
1319       
1320       std::ostringstream os;
1321       os << "Projections for " << rPhantom.name() << ": nDet=" << m_iDefaultNDet << ", nView=" << m_iDefaultNView << ", nSamples=" << m_iDefaultNSample << ", RotAngle=" << m_dDefaultRotation << ", FocalLengthRatio=" << m_dDefaultFocalLength << ", FieldOfViewRatio=" << m_dDefaultFieldOfView << ", Geometry=" << sGeometry.c_str();\r
1322       rProj.setCalcTime (timer.timerEnd());
1323       rProj.setRemark (os.str());
1324       *theApp->getLog() << os.str().c_str() << "\n";
1325       
1326       m_frame->Lower();
1327       ::wxYield();
1328       ProjectionFileView* projView = dynamic_cast<ProjectionFileView*>(pProjectionDoc->GetFirstView());\r
1329       if (projView) {\r
1330         projView->getFrame()->SetFocus();\r
1331         projView->OnUpdate (projView, NULL);\r
1332       }\r
1333       if (wxView* pView = pProjectionDoc->GetFirstView()) {
1334         if (wxFrame* pFrame = pView->GetFrame()) {
1335           pFrame->SetFocus();
1336           pFrame->Raise();
1337         }
1338         theApp->getDocManager()->ActivateView (pView, true, false);
1339       }
1340       ::wxYield();
1341       if (theApp->getSetModifyNewDocs())\r
1342         pProjectionDoc->Modify(true);
1343       pProjectionDoc->UpdateAllViews(this);
1344     }
1345   }
1346 }
1347
1348
1349 void
1350 PhantomView::OnRasterize (wxCommandEvent& event)
1351 {
1352   DialogGetRasterParameters dialogRaster (m_frame, 256, 256, 1);
1353   int retVal = dialogRaster.ShowModal();
1354   if (retVal == wxID_OK) {
1355     int xSize = dialogRaster.getXSize();
1356     int ySize = dialogRaster.getYSize();
1357     int nSamples = dialogRaster.getNSamples();\r
1358     if (nSamples < 1)
1359       nSamples = 1;
1360     if (xSize > 0 && ySize > 0) {
1361       const Phantom& rPhantom = GetDocument()->getPhantom();
1362       ImageFileDocument* pRasterDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
1363       if (! pRasterDoc) {\r
1364         sys_error (ERR_SEVERE, "Unable to create image file");\r
1365         return;\r
1366       }
1367       ImageFile& imageFile = pRasterDoc->getImageFile();
1368       
1369       imageFile.setArraySize (xSize, ySize);
1370       wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, m_frame, wxPD_CAN_ABORT);\r
1371       Timer timer;
1372       for (unsigned int i = 0; i < imageFile.nx(); i++) {
1373         rPhantom.convertToImagefile (imageFile, nSamples, Trace::TRACE_NONE, i, 1, true);
1374         if (! dlgProgress.Update(i+1)) {
1375           pRasterDoc->DeleteAllViews();
1376           return;
1377         }
1378       }
1379       if (theApp->getSetModifyNewDocs())\r
1380         pRasterDoc->Modify(true);
1381       pRasterDoc->UpdateAllViews(this);\r
1382       std::ostringstream os;\r
1383       os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << xSize << ", YSize=" << ySize << ", nSamples=" << nSamples;\r
1384       *theApp->getLog() << os.str().c_str() << "\n";\r
1385       imageFile.labelAdd (os.str().c_str(), timer.timerEnd());
1386       ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pRasterDoc->GetFirstView());\r
1387       if (rasterView) {\r
1388         rasterView->getFrame()->SetFocus();\r
1389         rasterView->OnUpdate (rasterView, NULL);\r
1390       }\r
1391       
1392     }\r
1393   }
1394 }
1395
1396
1397 PhantomCanvas* 
1398 PhantomView::CreateCanvas (wxView *view, wxFrame *parent)
1399 {
1400   PhantomCanvas* pCanvas;
1401   int width, height;
1402   parent->GetClientSize(&width, &height);
1403   
1404   pCanvas = new PhantomCanvas (dynamic_cast<PhantomView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1405   
1406   pCanvas->SetBackgroundColour(*wxWHITE);
1407   pCanvas->Clear();
1408   
1409   return pCanvas;
1410 }
1411
1412 wxFrame*
1413 PhantomView::CreateChildFrame(wxDocument *doc, wxView *view)
1414 {
1415   wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1416   
1417   wxMenu *file_menu = new wxMenu;
1418   
1419   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1420   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
1421   file_menu->Append(wxID_OPEN, "&Open...");\r
1422   file_menu->Append(wxID_SAVEAS, "Save &As...");\r
1423   file_menu->Append(wxID_CLOSE, "&Close");
1424   
1425   file_menu->AppendSeparator();
1426   file_menu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties");
1427   
1428   file_menu->AppendSeparator();
1429   file_menu->Append(wxID_PRINT, "&Print...");
1430   file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1431   file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1432   
1433   wxMenu *process_menu = new wxMenu;
1434   process_menu->Append(PHMMENU_PROCESS_RASTERIZE, "&Rasterize...");
1435   process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, "&Projections...");
1436   
1437   wxMenu *help_menu = new wxMenu;
1438   help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1439   help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1440   
1441   wxMenuBar *menu_bar = new wxMenuBar;
1442   
1443   menu_bar->Append(file_menu, "&File");
1444   menu_bar->Append(process_menu, "&Process");
1445   menu_bar->Append(help_menu, "&Help");
1446   
1447   subframe->SetMenuBar(menu_bar);
1448   
1449   subframe->Centre(wxBOTH);
1450   
1451   return subframe;
1452 }
1453
1454
1455 bool 
1456 PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1457 {
1458   m_frame = CreateChildFrame(doc, this);
1459   SetFrame(m_frame);
1460   
1461   int width, height;
1462   m_frame->GetClientSize(&width, &height);
1463   m_frame->SetTitle("PhantomView");
1464   m_canvas = CreateCanvas(this, m_frame);
1465   
1466 #ifdef __X__
1467   int x, y;  // X requires a forced resize
1468   m_frame->GetSize(&x, &y);
1469   m_frame->SetSize(-1, -1, x, y);
1470 #endif
1471   
1472   m_frame->Show(true);
1473   Activate(true);
1474   
1475   return true;
1476 }
1477
1478
1479 void 
1480 PhantomView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1481 {
1482   if (m_canvas)
1483     m_canvas->Refresh();
1484 }
1485
1486 bool 
1487 PhantomView::OnClose (bool deleteWindow)
1488 {
1489   if (!GetDocument()->Close())
1490     return false;
1491   
1492   m_canvas->Clear();
1493   m_canvas->m_pView = NULL;
1494   m_canvas = NULL;
1495   wxString s(wxTheApp->GetAppName());
1496   if (m_frame)
1497     m_frame->SetTitle(s);
1498   SetFrame(NULL);
1499   
1500   Activate(false);
1501   
1502   if (deleteWindow) {
1503     delete m_frame;
1504     return true;
1505   }
1506   return true;
1507 }
1508
1509 void
1510 PhantomView::OnDraw (wxDC* dc)
1511 {
1512   int xsize, ysize;
1513   m_canvas->GetClientSize (&xsize, &ysize);
1514   SGPDriver driver (dc, xsize, ysize);
1515   SGP sgp (driver);
1516   const Phantom& rPhantom = GetDocument()->getPhantom();
1517   sgp.setColor (C_RED);
1518   rPhantom.show (sgp);
1519 }
1520
1521 // ProjectionCanvas
1522
1523 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1524 : wxScrolledWindow(frame, -1, pos, size, style)
1525 {
1526   m_pView = v;
1527 }
1528
1529 void 
1530 ProjectionFileCanvas::OnDraw(wxDC& dc)
1531 {
1532   if (m_pView)
1533     m_pView->OnDraw(& dc);
1534 }
1535
1536 // ProjectionFileView
1537
1538 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
1539
1540 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
1541 EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
1542 EVT_MENU(PJMENU_PROCESS_RECONSTRUCT, ProjectionFileView::OnReconstruct)
1543 END_EVENT_TABLE()
1544
1545 ProjectionFileView::ProjectionFileView(void) 
1546 : wxView(), m_canvas(NULL), m_frame(NULL)
1547 {
1548   m_iDefaultNX = 256;
1549   m_iDefaultNY = 256;
1550   m_iDefaultFilter = SignalFilter::FILTER_ABS_BANDLIMIT;
1551   m_dDefaultFilterParam = 1.;
1552 #if HAVE_FFTW
1553   m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_RFFTW;
1554   m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER;
1555 #else
1556   m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_CONVOLUTION;
1557   m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT;
1558 #endif
1559   m_iDefaultZeropad = 1;
1560   m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF3;
1561   m_iDefaultInterpolation = Backprojector::INTERP_LINEAR;
1562   m_iDefaultInterpParam = 1;
1563   m_iDefaultTrace = Trace::TRACE_NONE;
1564 }
1565
1566 ProjectionFileView::~ProjectionFileView(void)
1567 {
1568 }
1569
1570 void
1571 ProjectionFileView::OnProperties (wxCommandEvent& event)
1572 {
1573   const Projections& rProj = GetDocument()->getProjections();
1574   std::ostringstream os;
1575   rProj.printScanInfo(os);
1576   *theApp->getLog() << os.str().c_str();
1577   wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Projection File Properties", wxOK | wxICON_INFORMATION);
1578   dialogMsg.ShowModal();
1579 }
1580
1581
1582 void
1583 ProjectionFileView::OnReconstruct (wxCommandEvent& event)
1584 {
1585   DialogGetReconstructionParameters dialogReconstruction (m_frame, m_iDefaultNX, m_iDefaultNY, m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, m_iDefaultTrace);
1586   
1587   int retVal = dialogReconstruction.ShowModal();
1588   if (retVal == wxID_OK) {
1589     m_iDefaultNX = dialogReconstruction.getXSize();
1590     m_iDefaultNY = dialogReconstruction.getYSize();
1591     wxString optFilterName = dialogReconstruction.getFilterName();
1592     m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.c_str());
1593     m_dDefaultFilterParam = dialogReconstruction.getFilterParam();
1594     wxString optFilterMethodName = dialogReconstruction.getFilterMethodName();
1595     m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.c_str());
1596     m_iDefaultZeropad = dialogReconstruction.getZeropad();
1597     wxString optFilterGenerationName = dialogReconstruction.getFilterGenerationName();
1598     m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.c_str());
1599     wxString optInterpName = dialogReconstruction.getInterpName();
1600     m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.c_str());
1601     m_iDefaultInterpParam = dialogReconstruction.getInterpParam();
1602     wxString optBackprojectName = dialogReconstruction.getBackprojectName();
1603     m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str());
1604     m_iDefaultTrace = dialogReconstruction.getTrace();
1605     if (m_iDefaultNX > 0 && m_iDefaultNY > 0) {
1606       ImageFileDocument* pReconDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
1607       if (! pReconDoc) {\r
1608         sys_error (ERR_SEVERE, "Unable to create image file");\r
1609         return;\r
1610       }
1611       ImageFile& imageFile = pReconDoc->getImageFile();
1612       const Projections& rProj = GetDocument()->getProjections();
1613       imageFile.setArraySize (m_iDefaultNX, m_iDefaultNY);
1614       
1615       if (m_iDefaultFilterMethod != ProcessSignal::FILTER_METHOD_CONVOLUTION && m_iDefaultFilterGeneration == ProcessSignal::FILTER_GENERATION_DIRECT && rProj.geometry() != Scanner::GEOMETRY_PARALLEL) {
1616         wxMessageBox ("Sorry!\nCurrently, frequency-based filtering with direct filter generation is not support for geometries other than parallel.\nAborting command.", "Not Supported", wxOK | wxICON_WARNING, m_frame);
1617         return;
1618       }
1619 \r
1620       Reconstructor* pReconstruct = new Reconstructor (rProj, imageFile, optFilterName.c_str(), m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace);
1621 \r
1622       Timer timerRecon;
1623       if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
1624         ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstruct, rProj, imageFile, m_iDefaultTrace, m_frame);
1625         for (int iView = 0; iView < rProj.nView(); iView++) {
1626           ::wxYield();
1627           ::wxYield();
1628           if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView)) {
1629             delete pDlgReconstruct;
1630             delete pReconstruct;
1631             pReconDoc->DeleteAllViews();
1632             return;
1633           }
1634           ::wxYield();
1635           ::wxYield();
1636           while (pDlgReconstruct->isPaused()) {
1637             ::wxYield();
1638             ::wxUsleep(50);
1639           }
1640         }
1641         delete pDlgReconstruct;
1642       } else {
1643         wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, m_frame, wxPD_CAN_ABORT);
1644         for (int i = 0; i < rProj.nView(); i++) {
1645           pReconstruct->reconstructView (i, 1);
1646           if (! dlgProgress.Update(i + 1)) {
1647             delete pReconstruct;
1648             pReconDoc->DeleteAllViews();
1649             return;
1650           }
1651         }
1652       }
1653       delete pReconstruct;
1654       if (theApp->getSetModifyNewDocs())\r
1655         pReconDoc->Modify(true);
1656       pReconDoc->UpdateAllViews(this);
1657       ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pReconDoc->GetFirstView());\r
1658       if (rasterView) {\r
1659         rasterView->getFrame()->SetFocus();\r
1660         rasterView->OnUpdate (rasterView, NULL);\r
1661       }\r
1662       std::ostringstream os;
1663       os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str();
1664       *theApp->getLog() << os.str().c_str() << "\n";
1665       imageFile.labelAdd (rProj.getLabel());
1666       imageFile.labelAdd (os.str().c_str(), timerRecon.timerEnd());
1667     }
1668   }
1669 }
1670
1671
1672 ProjectionFileCanvas* 
1673 ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent)
1674 {
1675   ProjectionFileCanvas* pCanvas;
1676   int width, height;
1677   parent->GetClientSize(&width, &height);
1678   
1679   pCanvas = new ProjectionFileCanvas (dynamic_cast<ProjectionFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1680   
1681   pCanvas->SetScrollbars(20, 20, 50, 50);
1682   pCanvas->SetBackgroundColour(*wxWHITE);
1683   pCanvas->Clear();
1684   
1685   return pCanvas;
1686 }
1687
1688 wxFrame*
1689 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
1690 {
1691   wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
1692   
1693   wxMenu *file_menu = new wxMenu;
1694   
1695   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1696   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
1697   file_menu->Append(wxID_OPEN, "&Open...");
1698   file_menu->Append(wxID_SAVE, "&Save");
1699   file_menu->Append(wxID_SAVEAS, "Save &As...");
1700   file_menu->Append(wxID_CLOSE, "&Close");
1701   
1702   file_menu->AppendSeparator();
1703   file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
1704   
1705   file_menu->AppendSeparator();
1706   file_menu->Append(wxID_PRINT, "&Print...");
1707   file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1708   file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1709   
1710   wxMenu *process_menu = new wxMenu;
1711   process_menu->Append(PJMENU_PROCESS_RECONSTRUCT, "R&econstruct...");
1712   
1713   wxMenu *help_menu = new wxMenu;
1714   help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1715   help_menu->AppendSeparator();
1716   help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1717   
1718   wxMenuBar *menu_bar = new wxMenuBar;
1719   
1720   menu_bar->Append(file_menu, "&File");
1721   menu_bar->Append(process_menu, "&Process");
1722   menu_bar->Append(help_menu, "&Help");
1723   
1724   subframe->SetMenuBar(menu_bar);
1725   
1726   subframe->Centre(wxBOTH);
1727   
1728   return subframe;
1729 }
1730
1731
1732 bool 
1733 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1734 {
1735   m_frame = CreateChildFrame(doc, this);
1736   SetFrame(m_frame);
1737   
1738   int width, height;
1739   m_frame->GetClientSize(&width, &height);
1740   m_frame->SetTitle("ProjectionFileView");
1741   m_canvas = CreateCanvas(this, m_frame);
1742   
1743 #ifdef __X__
1744   int x, y;  // X requires a forced resize
1745   m_frame->GetSize(&x, &y);
1746   m_frame->SetSize(-1, -1, x, y);
1747 #endif
1748   
1749   m_frame->Show(true);
1750   Activate(true);
1751   
1752   return true;
1753 }
1754
1755 void 
1756 ProjectionFileView::OnDraw (wxDC* dc)
1757 {
1758   if (m_bitmap.Ok())
1759     dc->DrawBitmap (m_bitmap, 0, 0, false);
1760 }
1761
1762
1763 void 
1764 ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
1765 {
1766   const Projections& rProj = GetDocument()->getProjections();
1767   const int nDet = rProj.nDet();
1768   const int nView = rProj.nView();
1769   if (nDet != 0 && nView != 0) {
1770     const DetectorArray& detarray = rProj.getDetectorArray(0);
1771     const DetectorValue* detval = detarray.detValues();
1772     double min = detval[0];
1773     double max = detval[0];
1774     for (int iy = 0; iy < nView; iy++) {
1775       const DetectorArray& detarray = rProj.getDetectorArray(iy);
1776       const DetectorValue* detval = detarray.detValues();
1777       for (int ix = 0; ix < nDet; ix++) {
1778         if (min > detval[ix])
1779           min = detval[ix];
1780         else if (max < detval[ix])
1781           max = detval[ix];
1782       }
1783     }
1784     
1785     unsigned char* imageData = new unsigned char [nDet * nView * 3];
1786     double scale = (max - min) / 255;
1787     for (int iy2 = 0; iy2 < nView; iy2++) {
1788       const DetectorArray& detarray = rProj.getDetectorArray (iy2);
1789       const DetectorValue* detval = detarray.detValues();
1790       for (int ix = 0; ix < nDet; ix++) {
1791         int intensity = static_cast<int>(((detval[ix] - min) / scale) + 0.5);
1792         intensity = clamp(intensity, 0, 255);
1793         int baseAddr = (iy2 * nDet + ix) * 3;
1794         imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
1795       }
1796     }
1797     wxImage image (nDet, nView, imageData, true);
1798     m_bitmap = image.ConvertToBitmap();
1799     delete imageData;
1800     int xSize = nDet;
1801     int ySize = nView;
1802     xSize = clamp (xSize, 0, 800);
1803     ySize = clamp (ySize, 0, 800);
1804     m_frame->SetClientSize (xSize, ySize);
1805     m_canvas->SetScrollbars (20, 20, nDet/20, nView/20);
1806   }
1807   
1808   if (m_canvas)
1809     m_canvas->Refresh();
1810 }
1811
1812 bool 
1813 ProjectionFileView::OnClose (bool deleteWindow)
1814 {
1815   if (!GetDocument()->Close())
1816     return false;
1817   
1818   m_canvas->Clear();
1819   m_canvas->m_pView = NULL;
1820   m_canvas = NULL;
1821   wxString s(wxTheApp->GetAppName());
1822   if (m_frame)
1823     m_frame->SetTitle(s);
1824   SetFrame(NULL);
1825   
1826   Activate(false);
1827   
1828   if (deleteWindow) {
1829     delete m_frame;
1830     return true;
1831   }
1832   return true;
1833 }
1834
1835
1836
1837 // PlotFileCanvas
1838 PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1839 : wxScrolledWindow(frame, -1, pos, size, style)
1840 {
1841   m_pView = v;
1842 }
1843
1844 void 
1845 PlotFileCanvas::OnDraw(wxDC& dc)
1846 {
1847   if (m_pView)
1848     m_pView->OnDraw(& dc);
1849 }\r
1850
1851
1852 // PlotFileView
1853
1854 IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
1855
1856 BEGIN_EVENT_TABLE(PlotFileView, wxView)
1857 EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
1858 EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax)\r
1859 EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto)\r
1860 END_EVENT_TABLE()
1861
1862 PlotFileView::PlotFileView(void) 
1863 : wxView(), m_canvas(NULL), m_frame(NULL), m_pEZPlot(NULL)
1864 {
1865 }
1866
1867 PlotFileView::~PlotFileView(void)
1868 {\r
1869   if (m_pEZPlot)\r
1870     delete m_pEZPlot;
1871 }
1872
1873 void
1874 PlotFileView::OnProperties (wxCommandEvent& event)
1875 {
1876   const PlotFile& rPlot = GetDocument()->getPlotFile();
1877   std::ostringstream os;\r
1878   os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";\r
1879   rPlot.printHeaders (os);
1880   *theApp->getLog() << os.str().c_str();
1881   wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
1882   dialogMsg.ShowModal();
1883 }
1884
1885
1886 void \r
1887 PlotFileView::OnScaleAuto (wxCommandEvent& event)\r
1888 {\r
1889   const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
1890   double min, max, mean, mode, median, stddev;\r
1891   rPlotFile.statistics (1, min, max, mean, mode, median, stddev);\r
1892   DialogAutoScaleParameters dialogAutoScale (m_frame, mean, mode, median, stddev, m_dAutoScaleFactor);\r
1893   int iRetVal = dialogAutoScale.ShowModal();\r
1894   if (iRetVal == wxID_OK) {\r
1895     m_bMinSpecified = true;\r
1896     m_bMaxSpecified = true;\r
1897     double dMin, dMax;\r
1898     if (dialogAutoScale.getMinMax (&dMin, &dMax)) {\r
1899       m_dMinPixel = dMin;\r
1900       m_dMaxPixel = dMax;\r
1901       m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();\r
1902       OnUpdate (this, NULL);\r
1903     }\r
1904   }\r
1905 }\r
1906 \r
1907 void \r
1908 PlotFileView::OnScaleMinMax (wxCommandEvent& event)\r
1909 {\r
1910   const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
1911   double min;\r
1912   double max;\r
1913 \r
1914   if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
1915     if (! rPlotFile.getMinMax (1, min, max)) {\r
1916       *theApp->getLog() << "Error: unable to find Min/Max\n";\r
1917       return;\r
1918     }\r
1919   }\r
1920   \r
1921   if (m_bMinSpecified)\r
1922     min = m_dMinPixel;\r
1923   if (m_bMaxSpecified)\r
1924     max = m_dMaxPixel;\r
1925   \r
1926   DialogGetMinMax dialogMinMax (m_frame, "Set Y-axis Minimum & Maximum", min, max);\r
1927   int retVal = dialogMinMax.ShowModal();\r
1928   if (retVal == wxID_OK) {\r
1929     m_bMinSpecified = true;\r
1930     m_bMaxSpecified = true;\r
1931     m_dMinPixel = dialogMinMax.getMinimum();\r
1932     m_dMaxPixel = dialogMinMax.getMaximum();\r
1933     OnUpdate (this, NULL);\r
1934   }\r
1935 }\r
1936 \r
1937 \r
1938 PlotFileCanvas* 
1939 PlotFileView::CreateCanvas (wxView *view, wxFrame *parent)
1940 {
1941   PlotFileCanvas* pCanvas;
1942   int width, height;
1943   parent->GetClientSize(&width, &height);
1944   
1945   pCanvas = new PlotFileCanvas (dynamic_cast<PlotFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1946   
1947   pCanvas->SetBackgroundColour(*wxWHITE);
1948   pCanvas->Clear();
1949   
1950   return pCanvas;
1951 }
1952
1953 wxFrame*
1954 PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
1955 {
1956   wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
1957   
1958   wxMenu *file_menu = new wxMenu;
1959   
1960   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
1961   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
1962   file_menu->Append(wxID_OPEN, "&Open...");
1963   file_menu->Append(wxID_SAVE, "&Save");
1964   file_menu->Append(wxID_SAVEAS, "Save &As...");
1965   file_menu->Append(wxID_CLOSE, "&Close");
1966   
1967   file_menu->AppendSeparator();
1968   file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
1969   
1970   file_menu->AppendSeparator();
1971   file_menu->Append(wxID_PRINT, "&Print...");
1972   file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1973   file_menu->Append(wxID_PREVIEW, "Print Pre&view");
1974   
1975   wxMenu *view_menu = new wxMenu;\r
1976   view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");\r
1977   view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");\r
1978   \r
1979   wxMenu *help_menu = new wxMenu;
1980   help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
1981   help_menu->AppendSeparator();
1982   help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1983   
1984   wxMenuBar *menu_bar = new wxMenuBar;
1985   
1986   menu_bar->Append(file_menu, "&File");\r
1987   menu_bar->Append(view_menu, "&View");
1988   menu_bar->Append(help_menu, "&Help");
1989   
1990   subframe->SetMenuBar(menu_bar);
1991   
1992   subframe->Centre(wxBOTH);
1993   
1994   return subframe;
1995 }
1996
1997
1998 bool 
1999 PlotFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
2000 {
2001   m_frame = CreateChildFrame(doc, this);
2002   SetFrame(m_frame);
2003   
2004   m_bMinSpecified = false;\r
2005   m_bMaxSpecified = false;\r
2006   m_dAutoScaleFactor = 1.;\r
2007   \r
2008   int width, height;
2009   m_frame->GetClientSize(&width, &height);
2010   m_frame->SetTitle ("Plot File");
2011   m_canvas = CreateCanvas (this, m_frame);
2012   
2013 #ifdef __X__
2014   int x, y;  // X requires a forced resize
2015   m_frame->GetSize(&x, &y);
2016   m_frame->SetSize(-1, -1, x, y);
2017 #endif
2018   
2019   m_frame->Show(true);
2020   Activate(true);
2021    
2022   return true;
2023 }
2024
2025 void 
2026 PlotFileView::OnDraw (wxDC* dc)
2027 {
2028   const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
2029   const int iNColumns = rPlotFile.getNumColumns();\r
2030   const int iNRecords = rPlotFile.getNumRecords();\r
2031   \r
2032   if (iNColumns > 0 && iNRecords > 0) {\r
2033     int xsize, ysize;\r
2034     m_canvas->GetClientSize (&xsize, &ysize);\r
2035     SGPDriver driver (dc, xsize, ysize);\r
2036     SGP sgp (driver);\r
2037     if (m_pEZPlot)\r
2038       m_pEZPlot->plot (&sgp);\r
2039   }\r
2040 }
2041
2042
2043 void 
2044 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2045 {
2046     const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
2047     const int iNColumns = rPlotFile.getNumColumns();\r
2048     const int iNRecords = rPlotFile.getNumRecords();\r
2049     \r
2050     if (iNColumns > 0 && iNRecords > 0) {\r
2051       if (m_pEZPlot)\r
2052         delete m_pEZPlot;\r
2053       m_pEZPlot = new EZPlot;\r
2054       \r
2055       for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)\r
2056         m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));\r
2057       \r
2058       if (m_bMinSpecified) {\r
2059         std::ostringstream os;\r
2060         os << "ymin " << m_dMinPixel;\r
2061         m_pEZPlot->ezset (os.str());\r
2062       }\r
2063       \r
2064       if (m_bMaxSpecified) {\r
2065         std::ostringstream os;\r
2066         os << "ymax " << m_dMaxPixel;\r
2067         m_pEZPlot->ezset (os.str());\r
2068       }\r
2069       \r
2070       m_pEZPlot->ezset("box");\r
2071       m_pEZPlot->ezset("grid");\r
2072       \r
2073       double* pdXaxis = new double [iNRecords];\r
2074       rPlotFile.getColumn (0, pdXaxis);\r
2075       \r
2076       double* pdY = new double [iNRecords];\r
2077       for (int iCol = 1; iCol < iNColumns; iCol++) {\r
2078         rPlotFile.getColumn (iCol, pdY);\r
2079         m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords);\r
2080       }\r
2081       \r
2082       delete pdXaxis;\r
2083       delete pdY;\r
2084     }\r
2085 \r
2086     if (m_canvas)\r
2087       m_canvas->Refresh();\r
2088 }
2089
2090 bool 
2091 PlotFileView::OnClose (bool deleteWindow)
2092 {
2093   if (!GetDocument()->Close())
2094     return false;
2095   
2096   m_canvas->Clear();
2097   m_canvas->m_pView = NULL;
2098   m_canvas = NULL;
2099   wxString s(wxTheApp->GetAppName());
2100   if (m_frame)
2101     m_frame->SetTitle(s);
2102   SetFrame(NULL);
2103   
2104   Activate(false);
2105   
2106   if (deleteWindow) {
2107     delete m_frame;
2108     return true;
2109   }
2110   return true;
2111 }
2112