background processing as well as taking advantage of multiple-CPU's
on SMP systems.
- * ctsim: Added PPM/PGM and PNG file import to imagefile.
-
- * ctsim: Added import of DICOM grayscale files.
-
- * ctsim: Added imagefile export to DICOM files.
-
- * ctsim: Added clipboard cut/copy/paste for image files.
-
+ * ctsim: Added plot t-theta sampling to projection file menu.
+
* ctsim: Added Reconstruction with Rebinning for faster
divergent beam reconstructions.
- * ctsim: Added plot t-theta sampling to projection file menu.
+ * ctsim: Added import and export of DICOM image files.
+
+ * ctsim: Added PPM, PGM, and PNG file import to imagefile.
+
+ * ctsim: Added FFT/IFFT of columns of image files.
+ * ctsim: Added clipboard cut/copy/paste for image files.
+
* ctsim: Added region of interest to reconstructions.
+ * ctsim: Added Convert Rectangular Image to Projection files
+
* ctsim: Added "Verbose Logging", "Startup Tips", and
"Background processes" options to Preferences dialog.
+ * ctsim: Added plotting of projection file histograms.
+
* plotfile: Added scattergram plot functions
* ctsim: Added accelerator key for File-Properties
+ * ctsim: Improved wireframe 3-d display to remove hidden
+ surfaces.
+
* sgp.cpp/ezplot.cpp: Improved plotting with markers.
* views.cpp: Added out of memory checks to display for huge
* sgp.cpp: Fixed bug in drawCircle
* filter.cpp: Fixed Hanning parameter to be 0.5 rather than 0.54
+
+ * imagefile.cpp: Fixed scaling factor in fftRows
+
+ * backprojectors.cpp: Added setting of axis extent and increment
+ to reconstructions.
3.0.3 - Released 2/20/01
* Scattergram of T-Theta sampling. Useful for understand divergent beam
scanning.
-* Added startup-tips to help new users learn features.
+* Startup-tips to help new users learn features.
-* Added ability to place detector at any arbitray position
+* Ability to place detector at any arbitray position
+* Histogram plotting of projection files
Version 3.0 New Features
* Plotting of row and column data of single and comparison images
-* Histogram Plotting
+* Histogram Plotting of Image files.
* Conversion of projections to polar images
reconstruction, rasterization, or projections, \ctsim\ will spawn
a \emph{Background Supervisor} thread. This supervisor thread then
creates a \emph{Supervisor Event Handler} (supervisor). The
-supervisor communicates with the rest of \ctsim\ by using message
-passing to avoid issues with re-entrant code.
-
-Though the various threads do not directly call each other, it is
-prudent to lock the class data structures with \emph{Critical
-Sections}. Critical sections lock areas of code and prevent more
-than one thread to access a section of code at a time. This is
-used when maintaining the tables of worker threads in the
-supervisor and also when maintaining the tables of supervisors in
-the background manager.
+supervisor communicates with the rest of graphical user interface
+of \ctsim\ by using message passing to avoid issues with
+re-entrant code.
The supervisor registers itself via message passing with the
\emph{Background Manager} which will display the execution
After registering with \ctsim\ components, the supervisor creates
\emph{Worker Threads}. These worker threads are the processes that
actually perform the calculations. By default, \ctsim\ will create
-one worker thread for every CPU in the system. The workers
-communicate with the supervisor via message passing. As the
-workers complete unit blocks, they send progress messages to the
-supervisor. The supervisor then sends progress messages to
-background manager which displays a gauge of the progress.
-
-After the workers have completed their tasks, they send a status
-message to the supervisor. When all the workers have finished, the
-supervisor will kill the worker threads. The supervisor then
-collates the work units from the workers and creates a new \ctsim\
-window to display the finished work.
+one worker thread for every CPU in the system. As the workers
+complete unit blocks, they notify the supervisor. The supervisor
+then sends progress messages to background manager which displays
+a gauge of the progress.
+
+As the worker threads directly call the supervisor, it is crucial
+to lock the class data structures with \emph{Critical Sections}.
+Critical sections lock areas of code and prevent more than one
+thread to access a section of code at a time. This is used when
+maintaining the tables of worker threads in the supervisor.
+
+After the workers have completed their tasks, they notify the
+supervisor. When all the workers have finished, the supervisor
+kills the worker threads. The supervisor then collates the work
+units from the workers and sends a message to \ctsim\ to create a
+new window to display the finished work.
The supervisor then deregisters itself via messages with the
background manager and the document. The background manager
several advantages:
\begin{itemize}
-\item Since the various threads do not call objects in other threads, problems
-with re-entrant code are eliminated.
+\item Since the background threads do not directly call objects in the graphical
+user interface thread, problems with re-entrant code in the
+graphical interface are eliminated.
\item A supervisor can parallel process with any number of worker threads
to take advantage of potentially large numbers of CPU's in SMP
computers.
results. When the worker threads finish, the supervisor allocates
memory for the final result and collates the results for the
workers. This collation results in a doubling of the memory
-requirements. Of course, after collation the supervisor
-deallocates the memory used by the workers.
+requirements. Of course, after collation the supervisor releases
+the memory used by the workers.
\item Slower execution on single CPU systems. \\
-The message passing between threads and collation
-of results for worker threads adds overhead compared to simply
-calculating the result directly in the foreground. On single CPU
-systems this results in slower processing compared to foreground
-processing. On dual-CPU and greater SMP systems, though, the
-advantage of using multiple CPU's in parallel exceeds the overhead
-of background processing.
+Creating multiple threads, sending progress messages to the
+background manager, and collation of results for worker threads
+adds overhead compared to simply calculating the result directly
+in the foreground. On single CPU systems this results in slower
+processing compared to foreground processing. On dual-CPU and
+greater SMP systems, though, the advantage of using multiple CPU's
+in parallel exceeds the overhead of background processing.
\end{itemize}
1
ctsim.tex
21
-4
-3
+0
+0
ctsim-algorithms.tex
TeX
-4091 0 65 52 0 43 44 44 960 631
+268439547 0 179 17 187 1 44 44 960 631
ctsim-concepts.tex
TeX
-12282 0 302 40 280 44 110 110 1187 697
+268447738 0 302 40 280 44 110 110 1187 697
ctsim.tex
TeX
-134230010 0 50 12 33 1 22 22 1099 609
+402665466 0 50 12 33 1 22 22 1099 609
ctsim-install.tex
TeX
268447738 0 70 62 71 1 110 110 1187 697
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: fourier.h,v 1.5 2001/01/28 19:20:15 kevin Exp $
+** $Id: fourier.h,v 1.6 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
static void shuffleFourierToNaturalOrder (float* pdVector, const int n);
static void shuffleFourierToNaturalOrder (double* pdVector, const int n);
static void shuffleFourierToNaturalOrder (std::complex<double>* pdVector, const int n);
+};
-}; // namespace Fourier
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: imagefile.h,v 1.33 2001/03/02 02:08:14 kevin Exp $
+** $Id: imagefile.h,v 1.34 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
static const int EXPORT_FORMAT_INVALID;
static const int IMPORT_FORMAT_INVALID;
+ static const int EXPORT_FORMAT_TEXT;
static const int EXPORT_FORMAT_PGM;
static const int EXPORT_FORMAT_PGMASCII;
static const int IMPORT_FORMAT_PPM;
bool importImage (const char* const pszFormat, const char* const pszFilename);
-#if HAVE_PNG
+#ifdef HAVE_PNG
bool writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax);
bool readImagePNG (const char* const pszFile);
#endif
-#if HAVE_GD
+#ifdef HAVE_GD
bool writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
#endif
bool writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
bool writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax);
bool readImagePPM (const char* const pszFile);
+ bool writeImageText (const char* const outfile);
static double redGrayscaleFactor() {return s_dRedGrayscaleFactor;}
static double greenGrayscaleFactor() {return s_dGreenGrayscaleFactor;}
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: backprojectors.cpp,v 1.31 2001/03/11 15:27:30 kevin Exp $
+** $Id: backprojectors.cpp,v 1.32 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
xInc = (xMax - xMin) / nx; // size of cells
yInc = (yMax - yMin) / ny;
+ im.setAxisIncrement (xInc, yInc);
+ im.setAxisExtent (xMin, xMax, yMin, yMax);
+
m_dFocalLength = proj.focalLength();
m_dSourceDetectorLength = proj.sourceDetectorLength();
}
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: fourier.cpp,v 1.4 2001/01/28 19:10:18 kevin Exp $
+** $Id: fourier.cpp,v 1.5 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
{
double* pdTemp = new double [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd(n)) { // Odd
int iHalfN = (n - 1) / 2;
pdTemp[0] = pdVector[iHalfN];
{
std::complex<double>* pdTemp = new std::complex<double> [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd(n)) { // Odd
int iHalfN = (n - 1) / 2;
pdTemp[0] = pdVector[iHalfN];
{
float* pdTemp = new float [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd (n)) { // Odd
int iHalfN = (n - 1) / 2;
pdTemp[0] = pdVector[iHalfN];
{
double* pdTemp = new double [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd(n)) { // Odd
int iHalfN = (n - 1) / 2;
pdTemp[iHalfN] = pdVector[0];
{
std::complex<double>* pdTemp = new std::complex<double> [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd(n)) { // Odd
int iHalfN = (n - 1) / 2;
pdTemp[iHalfN] = pdVector[0];
{
float* pTemp = new float [n];
int i;
- if (n % 2) { // Odd
+ if (isOdd (n)) { // Odd
int iHalfN = (n - 1) / 2;
pTemp[iHalfN] = pVector[0];
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: imagefile.cpp,v 1.40 2001/03/07 16:34:47 kevin Exp $
+** $Id: imagefile.cpp,v 1.41 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
const int ImageFile::EXPORT_FORMAT_INVALID = -1;
-const int ImageFile::EXPORT_FORMAT_PGM = 0;
-const int ImageFile::EXPORT_FORMAT_PGMASCII = 1;
+const int ImageFile::EXPORT_FORMAT_TEXT = 0;
+const int ImageFile::EXPORT_FORMAT_PGM = 1;
+const int ImageFile::EXPORT_FORMAT_PGMASCII = 2;
#ifdef HAVE_PNG
-const int ImageFile::EXPORT_FORMAT_PNG = 2;
-const int ImageFile::EXPORT_FORMAT_PNG16 = 3;
+const int ImageFile::EXPORT_FORMAT_PNG = 3;
+const int ImageFile::EXPORT_FORMAT_PNG16 = 4;
#endif
#ifdef HAVE_CTN_DICOM
-const int ImageFile::EXPORT_FORMAT_DICOM = 4;
+const int ImageFile::EXPORT_FORMAT_DICOM = 5;
#endif
const char* ImageFile::s_aszExportFormatName[] =
{
+ {"text"},
{"pgm"},
{"pgmascii"},
#ifdef HAVE_PNG
const char* ImageFile::s_aszExportFormatTitle[] =
{
+ {"Text"},
{"PGM"},
{"PGM ASCII"},
{"PNG"},
Fourier::shuffleFourierToNaturalOrder (pcRow, m_nx);
for (ix = 0; ix < m_nx; ix++) {
- vReal[ix][iy] = pcRow[ix].real();
- vImag[ix][iy] = pcRow[ix].imag();
+ vReal[ix][iy] = pcRow[ix].real() / m_nx;
+ vImag[ix][iy] = pcRow[ix].imag() / m_nx;
}
}
delete [] pcRow;
bool
ImageFile::fftCols (ImageFile& result) const
{
- return false;
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ fftw_complex* in = new fftw_complex [m_ny];
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+
+ fftw_plan plan = fftw_create_plan (m_ny, FFTW_FORWARD, FFTW_IN_PLACE);
+ std::complex<double>* pcCol = new std::complex<double> [m_ny];
+
+ unsigned int ix, iy;
+ unsigned int iArray = 0;
+ for (ix = 0; ix < m_nx; ix++) {
+ for (iy = 0; iy < m_ny; iy++) {
+ in[iy].re = vReal[ix][iy];
+ if (isComplex())
+ in[iy].im = vImag[ix][iy];
+ else
+ in[iy].im = 0;
+ }
+
+ fftw_one (plan, in, NULL);
+
+ for (iy = 0; iy < m_ny; iy++)
+ pcCol[iy] = std::complex<double>(in[iy].re, in[iy].im);
+
+ Fourier::shuffleFourierToNaturalOrder (pcCol, m_ny);
+ for (iy = 0; iy < m_ny; iy++) {
+ vReal[ix][iy] = pcCol[iy].real() / m_ny;
+ vImag[ix][iy] = pcCol[iy].imag() / m_ny;
+ }
+ }
+ delete [] pcCol;
+
+ fftw_destroy_plan (plan);
+ delete in;
+
+ return true;
}
bool
ImageFile::ifftCols (ImageFile& result) const
{
- return false;
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ fftw_complex* in = new fftw_complex [m_ny];
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+
+ fftw_plan plan = fftw_create_plan (m_ny, FFTW_BACKWARD, FFTW_IN_PLACE);
+ std::complex<double>* pcCol = new std::complex<double> [m_ny];
+
+ unsigned int ix, iy;
+ unsigned int iArray = 0;
+ for (ix = 0; ix < m_nx; ix++) {
+ for (iy = 0; iy < m_ny; iy++) {
+ double dImag = 0;
+ if (isComplex())
+ dImag = vImag[ix][iy];
+ pcCol[iy] = std::complex<double> (vReal[ix][iy], dImag);
+ }
+
+ Fourier::shuffleNaturalToFourierOrder (pcCol, m_ny);
+
+ for (iy = 0; iy < m_ny; iy++) {
+ in[iy].re = pcCol[iy].real();
+ in[iy].im = pcCol[iy].imag();
+ }
+
+ fftw_one (plan, in, NULL);
+
+ for (iy = 0; iy < m_ny; iy++) {
+ vReal[ix][iy] = in[iy].re;
+ vImag[ix][iy] = in[iy].im;
+ }
+ }
+ delete [] pcCol;
+
+ fftw_destroy_plan (plan);
+ delete in;
+
+ return true;
}
#endif // HAVE_FFTW
return writeImagePGM (pszFilename, nxcell, nycell, densmin, densmax);
else if (iFormatID == EXPORT_FORMAT_PGMASCII)
return writeImagePGMASCII (pszFilename, nxcell, nycell, densmin, densmax);
+ else if (iFormatID == EXPORT_FORMAT_TEXT)
+ return writeImageText (pszFilename);
+#ifdef HAVE_PNG
else if (iFormatID == EXPORT_FORMAT_PNG)
return writeImagePNG (pszFilename, 8, nxcell, nycell, densmin, densmax);
else if (iFormatID == EXPORT_FORMAT_PNG16)
return writeImagePNG (pszFilename, 16, nxcell, nycell, densmin, densmax);
+#endif
#ifdef HAVE_CTN_DICOM
else if (iFormatID == EXPORT_FORMAT_DICOM) {
DicomExporter dicomExport (this);
return true;
}
+bool
+ImageFile::writeImageText (const char* const outfile)
+{
+ FILE *fp;
+ int nx = m_nx;
+ int ny = m_ny;
+ ImageFileArray v = getArray();
+ ImageFileArray vImag = getImaginaryArray();
+
+ if ((fp = fopen (outfile, "w")) == NULL)
+ return false;
+
+ for (int irow = ny - 1; irow >= 0; irow--) {
+ for (int icol = 0; icol < nx; icol++) {
+ if (isComplex()) {
+ if (vImag[icol][irow] >= 0)
+ fprintf (fp, "%.9g+%.9gi ", v[icol][irow], vImag[icol][irow]);
+ else
+ fprintf (fp, "%.9g-%.9gi ", v[icol][irow], -vImag[icol][irow]);
+ } else
+ fprintf (fp, "%12.8g ", v[icol][irow]);
+ }
+ fprintf(fp, "\n");
+ }
+
+ fclose(fp);
+
+ return true;
+}
+
#ifdef HAVE_PNG
bool
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: procsignal.cpp,v 1.28 2001/03/13 14:53:44 kevin Exp $
+** $Id: procsignal.cpp,v 1.29 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
m_nFilterPoints = addZeropadFactor (m_nSignalPoints, m_iZeropad);
m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor;
- if (m_nFilterPoints % 2) { // Odd
+ if (isOdd (m_nFilterPoints)) { // Odd
m_dFilterMin = -1. / (2 * m_dSignalInc);
m_dFilterMax = 1. / (2 * m_dSignalInc);
m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1);
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: projections.cpp,v 1.66 2001/03/13 14:53:44 kevin Exp $
+** $Id: projections.cpp,v 1.67 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
// +1 is correct for frequency data, ndet-1 is correct for projections
int iDetCenter = (iNumDetWithZeros - 1) / 2; // index refering to L=0 projection
- if (iNumDetWithZeros % 2 == 0)
+ if (isEven (iNumDetWithZeros))
iDetCenter = (iNumDetWithZeros + 1) / 2;
// Calculates polar coordinates (view#, det#) for each point on phantom grid
#endif
pProjNew->m_detStart = -m_dViewDiameter / 2;
pProjNew->m_detInc = m_dViewDiameter / nDet;
- if (nDet % 2 == 0) // even
+ if (isEven (nDet)) // even
pProjNew->m_detInc = m_dViewDiameter / (nDet - 1);
ParallelRaysums parallel (this, ParallelRaysums::THETA_RANGE_NORMALIZE_TO_TWOPI);
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: scanner.cpp,v 1.36 2001/03/11 15:27:30 kevin Exp $
+** $Id: scanner.cpp,v 1.37 2001/03/18 18:08:25 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
double dDetectorArrayEndOffset = 0;
// For even number of detectors, make detInc slightly larger so that center lies
// at nDet/2. Also, extend detector array by one detInc so that all of the phantom is scanned
- if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+ if (isEven (m_nDet)) { // Adjust for Even number of detectors
m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
dDetectorArrayEndOffset = m_detInc;
}
m_detStart = -dHalfDetLen;
m_detInc = m_detLen / m_nDet;
double dDetectorArrayEndOffset = 0;
- if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+ if (isEven (m_nDet)) { // Adjust for Even number of detectors
m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
dDetectorArrayEndOffset = m_detInc;
m_detLen += dDetectorArrayEndOffset;
m_detStart = -dAngle;
m_detInc = m_detLen / m_nDet;
double dDetectorArrayEndOffset = 0;
- if (m_nDet % 2 == 0) { // Adjust for Even number of detectors
+ if (isEven (m_nDet)) { // Adjust for Even number of detectors
m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2)
dDetectorArrayEndOffset = m_detInc;
}
if (phm.getComposition() == P_UNIT_PULSE) { // put unit pulse in center of view
for (int d = 0; d < detArray.nDet(); d++)
- if (detArray.nDet() / 2 == d && (d % 2) == 1)
+ if (detArray.nDet() / 2 == d && isOdd (d))
detval[d] = 1;
else
detval[d] = 0;
--------------------Configuration: libctsim - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP282.tmp" with contents
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E5.tmp" with contents
[
/nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "..\..\..\wx2.2.5\src\png" /I "..\..\..\wx2.2.5\src\zlib" /I "..\..\INCLUDE" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2.2.5\include" /I "\dicom\ctn\include" /D "_DEBUG" /D "HAVE_WXWIN" /D "HAVE_STRING_H" /D "HAVE_GETOPT_H" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MSVC" /D "HAVE_FFTW" /D "HAVE_PNG" /D "HAVE_SGP" /D "HAVE_WXWINDOWS" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "HAVE_CTN_DICOM" /D VERSION=\"3.1.0\" /FR"Debug/" /Fp"Debug/libctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
-"C:\ctsim\libctsim\projections.cpp"
+"C:\ctsim\libctsim\imagefile.cpp"
]
-Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP282.tmp"
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP283.tmp" with contents
+Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E5.tmp"
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E6.tmp" with contents
[
/nologo /out:"Debug\libctsim.lib"
.\Debug\array2dfile.obj
.\Debug\transformmatrix.obj
.\Debug\xform.obj
]
-Creating command line "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP283.tmp"
+Creating command line "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E6.tmp"
<h3>Output Window</h3>
Compiling...
-projections.cpp
+imagefile.cpp
Creating library...
<h3>
--------------------Configuration: ctsim - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP284.tmp" with contents
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E7.tmp" with contents
[
winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib ctn_lib.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" /libpath:"\dicom\ctn\winctn\ctn_lib\Debug"
.\Debug\backgroundmgr.obj
\wx2.2.5\lib\zlibd.lib
\wx2.2.5\lib\tiffd.lib
]
-Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP284.tmp"
+Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP5E7.tmp"
<h3>Output Window</h3>
Linking...
** This is part of the CTSim program
** Copyright (C) 1983-2001 Kevin Rosenberg
**
-** $Id: backgroundmgr.cpp,v 1.19 2001/03/13 04:44:25 kevin Exp $
+** $Id: backgroundmgr.cpp,v 1.20 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
resizeWindow();
if (m_iNumTasks == 1) {
m_pCanvas->SetFocus();
- pGauge->SetFocus();
Show(true);
}
}
pSupervisor->ackRemoveBackgroundManager();
resizeWindow();
if (m_iNumTasks <= 0) {
- theApp->getMainFrame()->SetFocus();
+ m_pCanvas->SetFocus();
Show(false);
- theApp->getMainFrame()->SetFocus();
}
}
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: ctsim.h,v 1.59 2001/03/13 08:24:41 kevin Exp $
+** $Id: ctsim.h,v 1.60 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
PJMENU_RECONSTRUCT_FBP,
PJMENU_RECONSTRUCT_FBP_REBIN,
PJMENU_RECONSTRUCT_FOURIER,
+ PJMENU_CONVERT_RECTANGULAR,
PJMENU_CONVERT_POLAR,
PJMENU_CONVERT_FFT_POLAR,
PJMENU_CONVERT_PARALLEL,
PJMENU_PLOT_TTHETA_SAMPLING,
+ PJMENU_PLOT_HISTOGRAM,
PJMENU_ARTIFACT_REDUCTION,
IFMENU_FILE_EXPORT,
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: graph3dview.cpp,v 1.19 2001/03/13 04:44:25 kevin Exp $
+** $Id: graph3dview.cpp,v 1.20 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
// fNormalZ == Z vector for the normal vector
//*************************************************************************
-void
-CalculateVectorNormal (GLfloat fVert1[], GLfloat fVert2[],
- GLfloat fVert3[], GLfloat *fNormalX,
- GLfloat *fNormalY, GLfloat *fNormalZ)
-{
- GLfloat Qx = fVert2[0] - fVert1[0];
- GLfloat Qy = fVert2[1] - fVert1[1];
- GLfloat Qz = fVert2[2] - fVert1[2];
- GLfloat Px = fVert3[0] - fVert1[0];
- GLfloat Py = fVert3[1] - fVert1[1];
- GLfloat Pz = fVert3[2] - fVert1[2];
-
- *fNormalX = Py*Qz - Pz*Qy;
- *fNormalY = Pz*Qx - Px*Qz;
- *fNormalZ = Px*Qy - Py*Qx;
-
-}
-
-void
-CalculateVectorNormal (GLdouble fVert1[], GLdouble fVert2[],
- GLdouble fVert3[], GLdouble *fNormalX,
- GLdouble *fNormalY, GLdouble *fNormalZ)
+template<class T>
+static void
+CalculateVectorNormal (T fVert1[], T fVert2[], T fVert3[], T *fNormalX, T *fNormalY, T *fNormalZ)
{
- GLdouble Qx = fVert2[0] - fVert1[0];
- GLdouble Qy = fVert2[1] - fVert1[1];
- GLdouble Qz = fVert2[2] - fVert1[2];
- GLdouble Px = fVert3[0] - fVert1[0];
- GLdouble Py = fVert3[1] - fVert1[1];
- GLdouble Pz = fVert3[2] - fVert1[2];
+ T Qx = fVert2[0] - fVert1[0];
+ T Qy = fVert2[1] - fVert1[1];
+ T Qz = fVert2[2] - fVert1[2];
+ T Px = fVert3[0] - fVert1[0];
+ T Py = fVert3[1] - fVert1[1];
+ T Pz = fVert3[2] - fVert1[2];
*fNormalX = Py*Qz - Pz*Qy;
*fNormalY = Pz*Qx - Px*Qz;
*fNormalZ = Px*Qy - Py*Qx;
-
}
IMPLEMENT_DYNAMIC_CLASS(Graph3dFileView, wxView)
{
m_bDoubleBuffer = true;
m_bSmooth = true;
- m_bLighting = true;
- m_bSurface = true;
- m_bLighting = true;
- m_bColor = false;
- m_dXRotate = -45;
- m_dYRotate = 0;
- m_dZRotate = -45;
+ m_bLighting = false;
+ m_bSurface = false;
+ m_bLighting = false;
+ m_bColor = true;
+ m_dXRotate = -180;
+ m_dYRotate = -210;
+ m_dZRotate = -195;
m_bColorScaleMinSet = false;
m_bColorScaleMaxSet = false;
+ m_bCalculatedSurfaceBackground = false;
}
Graph3dFileView::~Graph3dFileView()
void
Graph3dFileView::DrawSurface()
{
+ if (! GetDocument())
+ return;
+
if (m_bSmooth) {
glShadeModel (GL_SMOOTH);
} else {
glDisable (GL_LIGHTING);
}
- if (m_bSurface)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- else
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- InitMaterials();
-
- if (! GetDocument())
- return;
-
unsigned int nx = GetDocument()->nx();
unsigned int ny = GetDocument()->ny();
+
glRotated (m_dZRotate, 0.0, 1.0, 0.0);
glRotated (m_dXRotate, 0.0, 0.0, 1.0);
glRotated (m_dYRotate, 1.0, 0.0, 0.0);
glTranslated (-static_cast<double>(nx - 1) / 2, 0.0, -static_cast<double>(ny - 1) / 2);
- glCallList (DISPLAYLIST_SURFACE);
+
+ InitMaterials();
+ if (m_bSurface) {
+ glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ if (! m_bColor) {
+ glColor3f (1.0f, 1.0f, 1.0f);
+ glCallList (DISPLAYLIST_NO_COLOR);
+ } else
+ glCallList (DISPLAYLIST_COLOR);
+ }
+ else {
+ if (! m_bColor)
+ glColor3f (1.0f, 1.0f, 1.0f);
+ glPolygonOffset (1.0f, 1.0f);
+ glEnable (GL_POLYGON_OFFSET_FILL);
+ glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ glCallList (DISPLAYLIST_COLOR);
+
+ glColor3f (0.0f, 0.0f, 0.0f);
+ glPolygonOffset (0.0f, 0.0f);
+ glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ glCallList (DISPLAYLIST_NO_COLOR);
+ }
+
}
void
if (nx == 0 || ny == 0 || ! v)
return;
- glNewList (DISPLAYLIST_SURFACE, GL_COMPILE);
+ glNewList (DISPLAYLIST_COLOR, GL_COMPILE);
double dMin = m_dColorScaleMin;
double dIntensityScale = m_dColorScaleMax - m_dColorScaleMin;
dXOffset = 0;
dYOffset = 0;
- if (! m_bColor)
- glColor3f (1.0f, 1.0f, 1.0f);
-
double dXPos = -dXOffset;
for (unsigned ix = 0; ix < nx - 1; ix++, dXPos++) {
double dYPos = -dYOffset;
p1[0] = dXPos; p1[1] = actScale * (v[ix][0] + actOffset); p1[2] = dYPos;
p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][0] + actOffset); p2[2] = dYPos;
p3[0] = dXPos; p3[1] = actScale * (v[ix][1] + actOffset); p3[2] = dYPos + 1;
- CalculateVectorNormal (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
+ CalculateVectorNormal<double> (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
double dIntensity1, dIntensity2;
if (m_bColor) {
}
glVertex3dv (p1);
glNormal3dv (n1);
- if (m_bColor) {
intensityToColor (dIntensity2, vecColor);
glColor3fv (vecColor);
- }
glVertex3dv (p2);
glNormal3dv (n1);
double lastP[3];
p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][iy] + actOffset); p2[2] = dYPos;
CalculateVectorNormal (p1, p2, lastP, &n1[0], &n1[1], &n1[2]);
lastP[0] = p1[0]; lastP[1] = p1[1]; lastP[2] = p1[2];
- if (m_bColor) {
dIntensity1 = (v[ix][iy] - dMin) / dIntensityScale;
dIntensity2 = (v[ix+1][iy] - dMin) / dIntensityScale;
- }
- if (m_bColor) {
intensityToColor (dIntensity1, vecColor);
glColor3fv (vecColor);
- }
glVertex3dv (p1); glNormal3dv (n1);
- if (m_bColor) {
intensityToColor (dIntensity2, vecColor);
glColor3fv (vecColor);
- }
+ glVertex3dv (p2); glNormal3dv (n1);
+ }
+ glEnd(); // QUAD_STRIP
+ }
+ glEndList();
+
+
+ glNewList (DISPLAYLIST_NO_COLOR, GL_COMPILE);
+ dXPos = -dXOffset;
+ for (ix = 0; ix < nx - 1; ix++, dXPos++) {
+ double dYPos = -dYOffset;
+ glBegin(GL_QUAD_STRIP);
+ double p1[3], p2[3], p3[3], n1[3];
+ p1[0] = dXPos; p1[1] = actScale * (v[ix][0] + actOffset); p1[2] = dYPos;
+ p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][0] + actOffset); p2[2] = dYPos;
+ p3[0] = dXPos; p3[1] = actScale * (v[ix][1] + actOffset); p3[2] = dYPos + 1;
+ CalculateVectorNormal<double> (p1, p2, p3, &n1[0], &n1[1], &n1[2]);
+
+ glVertex3dv (p1);
+ glNormal3dv (n1);
+ glVertex3dv (p2);
+ glNormal3dv (n1);
+ double lastP[3];
+ lastP[0] = ix; lastP[1] = actScale * (v[ix][0] + actOffset); lastP[2] = 0;
+ for (unsigned int iy = 1; iy < ny - 1; iy++, dYPos++) {
+ p1[0] = dXPos; p1[1] = actScale * (v[ix][iy] + actOffset); p1[2] = dYPos;
+ p2[0] = dXPos+1; p2[1] = actScale * (v[ix+1][iy] + actOffset); p2[2] = dYPos;
+ CalculateVectorNormal (p1, p2, lastP, &n1[0], &n1[1], &n1[2]);
+ lastP[0] = p1[0]; lastP[1] = p1[1]; lastP[2] = p1[2];
+ glVertex3dv (p1); glNormal3dv (n1);
glVertex3dv (p2); glNormal3dv (n1);
}
glEnd(); // QUAD_STRIP
}
+void
+Graph3dFileView::calculateSurfaceBackground ()
+{
+ if (m_bCalculatedSurfaceBackground)
+ return;
+}
+
void
Graph3dFileView::OnProperties (wxCommandEvent& event)
{
{
m_bColor = ! m_bColor;
m_pViewMenu->Check (GRAPH3D_VIEW_COLOR, m_bColor);
- OnUpdate (this, NULL);
+ m_pCanvas->Refresh();
}
void
#if 1
static float ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
static float diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
- static float position0[] = {-nx/2, -ny/2, -ny/2, 0.0f, 0.0f};
- static float position1[] = {-nx/2, -ny/2, ny/2, 0.0f};
+ static float position0[] = {-nx/2, -ny/2, ny/2, 0.0f, 0.0f};
+ static float position1[] = {-nx/2, -ny/2, -ny/2, 0.0f};
static float ambient1[] = {0.5f, 0.5f, 0.5f, 1.0f};
static float diffuse1[] = {1.0f, 1.0f, 1.0f, 1.0f};
// static float position0[] = {0.0f, 0.0f, 20.0f, 0.0f};
if (! m_bColorScaleMaxSet)
m_dColorScaleMax = max;
}
-
double dRadius = maxValue<int> (nx, ny) * SQRT2 / 2;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: graph3dview.h,v 1.6 2001/02/04 22:58:41 kevin Exp $
+** $Id: graph3dview.h,v 1.7 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
bool m_bSurface;
bool m_bColor;
enum {
- DISPLAYLIST_SURFACE = 1,
+ DISPLAYLIST_COLOR = 1,
+ DISPLAYLIST_NO_COLOR = 2,
};
double m_dGraphMin;
double m_dColorScaleMax;
bool m_bColorScaleMinSet;
bool m_bColorScaleMaxSet;
+ bool m_bCalculatedSurfaceBackground;
void Draw();
void DrawSurface();
void OnScaleSet (wxCommandEvent& event);
void OnScaleAuto (wxCommandEvent& event);
void OnScaleFull (wxCommandEvent& event);
+ void calculateSurfaceBackground();
#if CTSIM_MDI
wxDocMDIChildFrame* getFrame() { return m_pFrame; }
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: views.cpp,v 1.138 2001/03/13 10:35:06 kevin Exp $
+** $Id: views.cpp,v 1.139 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
view_menu->Append(IFMENU_VIEW_SCALE_FULL, "Display F&ull Scale\tCtrl-U");
wxMenu* filter_menu = new wxMenu;
- filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");
+ filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "In&vert Values");
filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");
filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");
filter_menu->Append (IFMENU_FILTER_LOG, "&Log");
accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('C'), IFMENU_EDIT_COPY);
accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('X'), IFMENU_EDIT_CUT);
accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('V'), IFMENU_EDIT_PASTE);
-#if wxUSE_GLCANVAS
+#ifdef wxUSE_GLCANVAS
accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('3'), IFMENU_IMAGE_CONVERT3D);
wxAcceleratorTable accelTable (8, accelEntries);
#else
strWildcard = "DICOM Files (*.*)|*.*";
}
#endif
+ else if (m_iDefaultExportFormatID == ImageFile::EXPORT_FORMAT_TEXT) {
+ strExt = ".txt";
+ strWildcard = "Text (*.txt)|*.txt";
+ }
else {
strExt = "";
strWildcard = "Miscellaneous (*.*)|*.*";
s += rIF.labelGet(iL).getLabelString();
rPlotFile.addDescription (s.c_str());
}
- os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
+ os << " plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
*theApp->getLog() << os.str().c_str() << "\n";
rPlotFile.addDescription (os.str().c_str());
delete pX;
EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
EVT_MENU(PJMENU_RECONSTRUCT_FBP_REBIN, ProjectionFileView::OnReconstructFBPRebin)
EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier)
+EVT_MENU(PJMENU_CONVERT_RECTANGULAR, ProjectionFileView::OnConvertRectangular)
EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
EVT_MENU(PJMENU_CONVERT_PARALLEL, ProjectionFileView::OnConvertParallel)
EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling)
+EVT_MENU(PJMENU_PLOT_HISTOGRAM, ProjectionFileView::OnPlotHistogram)
EVT_MENU(PJMENU_ARTIFACT_REDUCTION, ProjectionFileView::OnArtifactReduction)
END_EVENT_TABLE()
}
+void
+ProjectionFileView::OnConvertRectangular (wxCommandEvent& event)
+{
+ Projections& rProj = GetDocument()->getProjections();
+
+ int nDet = rProj.nDet();
+ int nView = rProj.nView();
+ ImageFile* pIF = new ImageFile (nDet, nView);
+ ImageFileArray v = pIF->getArray();
+ for (int iv = 0; iv < nView; iv++) {
+ DetectorValue* detval = rProj.getDetectorArray(iv).detValues();
+
+ for (int id = 0; id < nDet; id++)
+ v[id][iv] = detval[id];
+ }
+
+ ImageFileDocument* pRectDoc = theApp->newImageDoc ();
+ if (! pRectDoc) {
+ sys_error (ERR_SEVERE, "Unable to create image file");
+ return;
+ }
+ pRectDoc->setImageFile (pIF);
+ pIF->labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
+ std::ostringstream os;
+ os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to rectangular image";
+ *theApp->getLog() << os.str().c_str() << "\n";
+ pIF->labelAdd (os.str().c_str());
+ if (theApp->getAskDeleteNewDocs())
+ pRectDoc->Modify (true);
+ pRectDoc->getView()->getFrame()->Show(true);
+ pRectDoc->UpdateAllViews ();
+ pRectDoc->Activate();
+}
+
void
ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
{
pPlotDoc->Activate();
}
+
+void
+ProjectionFileView::OnPlotHistogram (wxCommandEvent& event)
+{
+ Projections& rProj = GetDocument()->getProjections();
+ int nDet = rProj.nDet();
+ int nView = rProj.nView();
+
+ if (nDet < 1 || nView < 1)
+ return;
+
+ PlotFileDocument* pPlotDoc = theApp->newPlotDoc();
+ if (! pPlotDoc) {
+ sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
+ return;
+ }
+
+ DetectorValue* pdDetval = rProj.getDetectorArray(0).detValues();
+ double dMin = pdDetval[0], dMax = pdDetval[0];
+
+ for (int iv = 0; iv < nView; iv++) {
+ pdDetval = rProj.getDetectorArray(iv).detValues();
+ for (int id = 0; id < nDet; id++) {
+ double dV = pdDetval[id];
+ if (dV < dMin)
+ dMin = dV;
+ else if (dV > dMax)
+ dMax = dV;
+ }
+ }
+
+ double* pX = new double [NUMBER_HISTOGRAM_BINS];
+ double* pY = new double [NUMBER_HISTOGRAM_BINS];
+ double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
+
+ for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
+ pX[i] = dMin + (i + 0.5) * dBinWidth;
+ pY[i] = 0;
+ }
+ for (int j = 0; j < nView; j++) {
+ pdDetval = rProj.getDetectorArray(j).detValues();
+ for (int id = 0; id < nDet; id++) {
+ int iBin = nearest<int> ((pdDetval[id] - dMin) / dBinWidth);
+ if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
+ pY[iBin] += 1;
+ }
+ }
+ PlotFile& rPlotFile = pPlotDoc->getPlotFile();
+ std::ostringstream os;
+ os << "Histogram";
+ std::string title("title ");
+ title += os.str();
+ rPlotFile.addEzsetCommand (title.c_str());
+ rPlotFile.addEzsetCommand ("xlabel Detector Value");
+ rPlotFile.addEzsetCommand ("ylabel Count");
+ rPlotFile.addEzsetCommand ("box");
+ rPlotFile.addEzsetCommand ("grid");
+ rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
+ rPlotFile.addColumn (0, pX);
+ rPlotFile.addColumn (1, pY);
+ rPlotFile.addDescription (rProj.remark());
+ os << " plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
+ *theApp->getLog() << os.str().c_str() << "\n";
+ rPlotFile.addDescription (os.str().c_str());
+ delete pX;
+ delete pY;
+ if (theApp->getAskDeleteNewDocs())
+ pPlotDoc->Modify (true);
+ pPlotDoc->getView()->getFrame()->Show(true);
+ pPlotDoc->UpdateAllViews ();
+ pPlotDoc->Activate();
+}
+
+
void
ProjectionFileView::OnConvertParallel (wxCommandEvent& event)
{
os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str();
if (bRebinToParallel)
os << "; Interpolate to Parallel";
-
+
Timer timerRecon;
ImageFile* pImageFile = NULL;
if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
GetDocumentManager()->FileHistoryUseMenu(m_pFileMenu);
wxMenu *convert_menu = new wxMenu;
+ convert_menu->Append (PJMENU_CONVERT_RECTANGULAR, "&Rectangular Image");
convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L");
- convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-M");
+ convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "FF&T->Polar Image...\tCtrl-T");
convert_menu->AppendSeparator();
convert_menu->Append (PJMENU_CONVERT_PARALLEL, "&Interpolate to Parallel");
filter_menu->Append (PJMENU_ARTIFACT_REDUCTION, "&Artifact Reduction");
wxMenu* analyze_menu = new wxMenu;
- analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "&Plot T-Theta Sampling\tCtrl-T");
-
+ analyze_menu->Append (PJMENU_PLOT_HISTOGRAM, "&Plot Histogram");
+ analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "Plot T-T&heta Sampling...\tCtrl-H");
+
wxMenu *reconstruct_menu = new wxMenu;
reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R", "Reconstruct image using filtered backprojection");
reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP_REBIN, "Filtered &Backprojection (Rebin to Parallel)...\tCtrl-B", "Reconstruct image using filtered backprojection");
wxAcceleratorEntry accelEntries[7];
accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
- accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('M'), PJMENU_CONVERT_FFT_POLAR);
+ accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_CONVERT_FFT_POLAR);
accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('B'), PJMENU_RECONSTRUCT_FBP_REBIN);
accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_FILE_PROPERTIES);
- accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('T'), PJMENU_PLOT_TTHETA_SAMPLING);
+ accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('H'), PJMENU_PLOT_TTHETA_SAMPLING);
wxAcceleratorTable accelTable (7, accelEntries);
subframe->SetAcceleratorTable (accelTable);
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: views.h,v 1.51 2001/03/13 08:24:41 kevin Exp $
+** $Id: views.h,v 1.52 2001/03/18 18:08:26 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
void OnReconstructFBP (wxCommandEvent& event);
void OnReconstructFBPRebin (wxCommandEvent& event);
void OnReconstructFourier (wxCommandEvent& event);
+ void OnConvertRectangular (wxCommandEvent& event);
void OnConvertPolar (wxCommandEvent& event);
void OnConvertFFTPolar (wxCommandEvent& event);
void OnPlotTThetaSampling (wxCommandEvent& event);
+ void OnPlotHistogram (wxCommandEvent& event);
void OnConvertParallel (wxCommandEvent& event);
void OnArtifactReduction (wxCommandEvent& event);