From d3fa225aa232e132cc198672c4fc148f96a1ab8c Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Sun, 11 Feb 2001 04:56:38 +0000 Subject: [PATCH] r520: no message --- doc/ctsim-concepts.tex | 155 ++++++++++++++++-------------- doc/ctsim-gui.tex | 103 +++++++++++--------- doc/ctsim-install.tex | 17 ++-- doc/ctsim-textui.tex | 155 ++++++++++++++++-------------- doc/ctsim-web.tex | 2 +- doc/ctsim.tex | 11 +-- doc/mytitle.sty | 2 +- include/Makefile.am | 2 +- include/backprojectors.h | 30 +----- include/ct.h | 4 +- include/filter.h | 5 +- libctsim/backprojectors.cpp | 184 ++++++------------------------------ libctsim/filter.cpp | 6 +- libctsim/procsignal.cpp | 6 +- libctsim/reconstruct.cpp | 14 ++- libctsupport/Makefile.am | 2 +- msvc/ctsim/ctsim.plg | 14 +-- src/ctsim.cpp | 22 +++-- src/ctsim.h | 16 +++- src/dialogs.cpp | 145 ++++++++++++++++++---------- src/dialogs.h | 10 +- src/views.cpp | 14 ++- tools/phm2pj.cpp | 15 ++- 23 files changed, 458 insertions(+), 476 deletions(-) diff --git a/doc/ctsim-concepts.tex b/doc/ctsim-concepts.tex index 81dbf42..ddf6bed 100644 --- a/doc/ctsim-concepts.tex +++ b/doc/ctsim-concepts.tex @@ -1,14 +1,15 @@ \chapter{Concepts}\index{Concepts}% \setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}% -\setfooter{\thepage}{}{}{}{}{\thepage}% +\setfooter{\thepage}{}{}{}{\small Version 0.2}{\thepage}% \section{Overview}\label{conceptoverview}\index{Concepts,Overview}% -The operation of \ctsim\ begins with the phantom object. A phantom -object consists of geometric elements. A scanner is specified and the -projection data simulated. Finally that projection data can be -reconstructed using various user controlled algorithms producing an -image of the phantom object. This reconstruction can then be -statistically compared to the original phantom object. +The operation of \ctsim\ begins with the phantom object. A +phantom object consists of geometric elements. A scanner is +specified and the collection of x-ray data, or projections, is +simulated. That projection data can be reconstructed using various +user-controlled algorithms producing an image of the phantom +object. This reconstruction can then be statistically compared to +the original phantom object. In order to use \ctsim\ effectively, some knowledge of how \ctsim\ works and the approach taken is required. \ctsim\ deals with a variety of @@ -18,14 +19,15 @@ object, but the two objects we need to be concerned with are the \section{Phantoms}\label{conceptphantom}\index{Concepts,Phantoms}% \subsection{Overview}\label{phantomoverview}\index{Concepts,Phantoms,Overview}% -\ctsim\ uses geometrical objects to -describe the object being scanned. A phantom is composed a one or more -phantom elements. These elements are simple geometric shapes, -specifically, rectangles, triangles, ellipses, sectors and segments. -With these elements, standard phantoms used in the CT literature can -be constructed. In fact, \ctsim\ provides a shortcut to load the -published phantoms of Herman and Shepp-Logan. \ctsim\ also reads text -files of user-defined phantoms. +\ctsim\ uses geometrical objects to describe the object being +scanned. A phantom is composed a one or more phantom elements. +These elements are simple geometric shapes, specifically, +rectangles, triangles, ellipses, sectors and segments. With these +elements, standard phantoms used in the CT literature can be +constructed. In fact, \ctsim\ provides a shortcut to load the +published phantoms of Herman\cite{HERMAN80} and +Shepp-Logan\cite{SHEPP74}. \ctsim\ also reads text files of +user-defined phantoms. The types of phantom elements and their definitions are taken with permission from G.T. Herman's 1980 book\cite{HERMAN80}. @@ -36,7 +38,7 @@ phantom. Each line contains seven entries, in the following form: \begin{verbatim} element-type cx cy dx dy r a \end{verbatim} -The first entry defines the type of the element, one of +The first entry defines the type of the element, either \rtfsp\texttt{rectangle}, \texttt{}, \texttt{triangle}, \rtfsp\texttt{sector}, or \texttt{segment}. \texttt{cx}, \rtfsp\texttt{cy}, \texttt{dx} and \texttt{dy} have different @@ -138,15 +140,16 @@ square These relationships are diagrammed in figure 2.1. \subsubsection{View Diameter} -The \emph{view diameter} is the area that is being processed during scanning of phantoms as -well as during rasterization of phantoms. By default, the \emph{view diameter} -\rtfsp is set equal to the \emph{phantom diameter}. It may be useful, especially for -experimental reasons, to process an area larger (and maybe even smaller) than -the phantom. Thus, during rasterization or during projections, \ctsim\ will -ask for a \emph{view ratio}, -\latexonly{$v_r$.}\latexignore{\rtfsp \emph{VR}.} -The \emph{view diameter} is then set as -\latexonly{$$v_d = p_d v_r$$}\latexignore{\\$$\emph{Vd = Pd x VR}$$} +The \emph{view diameter} is the area that is being processed +during scanning of phantoms as well as during rasterization of +phantoms. By default, the \emph{view diameter} \rtfsp is set equal +to the \emph{phantom diameter}. It may be useful, especially for +experimental reasons, to process an area larger (and maybe even +smaller) than the phantom. Thus, during rasterization or during +projections, \ctsim\ will ask for a \emph{view ratio}, +\latexonly{$v_r$.}\latexignore{\rtfsp \emph{VR}.} The \emph{view +diameter} is then calculated as \latexonly{$$v_d = p_d +v_r$$}\latexignore{\\$$\emph{Vd = Pd x VR}$$} By using a \latexonly{$v_r$}\latexignore{\emph{VR}} @@ -158,17 +161,17 @@ be impossible and is analagous to inserting an object into the CT scanner that is larger than the scanner itself! \subsubsection{Scan Diameter} -By default, the entire \emph{view diameter} is scanned. For experimental -purposes, it may be desirable to scan an area either larger or smaller than -the \emph{view diameter}. Thus, the concept of \emph{scan ratio} -\latexonly{$s_r$}\latexignore{\emph{SR}} +By default, the entire \emph{view diameter} is scanned. For +experimental purposes, it may be desirable to scan an area either +larger or smaller than the \emph{view diameter}. Thus, the concept +of \emph{scan ratio}, \latexonly{$s_r$,}\latexignore{\emph{SR},} is born. The scan diameter -\latexonly{$s_d$}\latexignore{\emph{Sd}} -is the diameter over which x-rays are collected and is defined as -\latexonly{$$s_d = v_d s_r$$}\latexignore{\\$$\emph{Sd = Vd x SR}$$\\} -By default and for all ordinary scanning, the \emph{scan ratio} is to -\texttt{1}. If the \emph{scan ratio} is less than \texttt{1}, -you can expect significant artifacts. +\latexonly{$s_d$}\latexignore{\emph{Sd}} is the diameter over +which x-rays are collected and is defined as \latexonly{$$s_d = +v_d s_r$$}\latexignore{\\$$\emph{Sd = Vd x SR}$$\\} By default and +for all ordinary scanning, the \emph{scan ratio} is to \texttt{1}. +If the \emph{scan ratio} is less than \texttt{1}, you can expect +significant artifacts. \subsubsection{Focal Length} The \emph{focal length}, @@ -180,9 +183,13 @@ of the view radius. Focal length is calculated as \latexonly{$$f = (v_d / 2) f_r$$}\latexignore{\\$$\emph{F = (Vd / 2) x FR}$$} -For parallel geometry scanning, the focal length doesn't matter. However, -divergent geometry scanning (equilinear and equiangular), the \emph{focal -length ratio} should be set at \texttt{2} or more to avoid artifacts. +For parallel geometry scanning, the focal length doesn't matter. +However, divergent geometry scanning (equilinear and equiangular), +the \emph{focal length ratio} should be set at \texttt{2} or more +to avoid artifacts. Moreover, a value of less than \texttt{1}, +though it can be given to \ctsim, is physically impossible and it +analagous to have having the x-ray source with the \emph{view +diameter}. \subsection{Parallel Geometry}\label{geometryparallel}\index{Concepts,Scanner,Geometries,Parallel} @@ -213,13 +220,14 @@ See figure 2.2. \subsubsection{Fan Beam Angle} -For these divergent beam geometries, the \emph{fan beam angle} needs -to be calculated. For real-world CT scanners, this is fixed at the -time of manufacture. \ctsim, however, calculates the \emph{fan beam angle}, -$\alpha$ from the \emph{scan diameter} and the \emph{focal length} -\latexignore{\\$$\emph{alpha = 2 x asin ( (Sd / 2) / f)}$$\\} -\latexonly{\begin{equation}\label{alphacalc}\alpha = 2 \sin^{-1} ((s_d / 2) / f)\end{equation}} -This is illustrated in figure 2.3. +For these divergent beam geometries, the \emph{fan beam angle} +needs to be calculated. For real-world CT scanners, this is fixed +at the time of manufacture. \ctsim, however, calculates the +\emph{fan beam angle}, $\alpha$, from the \emph{scan diameter} and +the \emph{focal length} \latexignore{\\$$\emph{alpha = 2 x asin ( +(Sd / 2) / f)}$$\\} +\latexonly{\begin{equation}\label{alphacalc}\alpha = 2 \sin^{-1} +((s_d / 2) / f)\end{equation}} This is illustrated in figure 2.3. \begin{figure} \image{10cm;0cm}{alphacalc.eps} \caption{Calculation of $\alpha$} @@ -236,37 +244,39 @@ there are significant artifacts. The primary way to manage the To illustrate, the \emph{scan diameter} can be defined as \latexonly{$$s_d = s_r v_r p_d$$}\latexignore{\\$$Sd = Sr x Vr x Pd$$\\} -Further, $f$ can be defined as -\latexonly{$$f = f_r (v_r p_d / 2)$$} -Plugging these equations into -\latexignore{the above equation,}\latexonly{equation~\ref{alphacalc},} -We have, +Further, $f$ can be defined as \latexonly{$$f = f_r (v_r p_d / +2)$$}\latexignore{\\$$F = FR x (VR x Pd)$$\\} + +Substituting these equations into \latexignore{the above +equation,}\latexonly{equation~\ref{alphacalc},} We have, \latexonly{ \begin{eqnarray} \alpha &= 2\,\sin^{-1} \frac{s_r v_r p_d / 2}{f_r v_r (p_d / 2)} \nonumber \\ &= 2\,\sin^{-1} (s_r / f_r) \end{eqnarray} -} +} \latexignore{\\$$\alpha = 2 sin (Sr / Fr$$\\} -Since in normal scanning $s_r = 1$, $\alpha$ depends only upon the \emph{focal length ratio}. +Since in normal scanning $s_r$ = 1, $\alpha$ depends only upon the +\emph{focal length ratio}. \subsubsection{Detector Array Size} -In general, you do not need to be concerned with the detector array -size. It is automatically calculated by \ctsim. +In general, you do not need to be concerned with the detector +array size. It is automatically calculated by \ctsim. For those +interested, this section explains how the detector array size is +calculated. For parallel geometry, the detector length is equal to the scan diameter. -For divergent beam geometrys, the size of the -detector array also depends upon the \emph{focal length}. -Increasing the \emph{focal length} -decreases the size of the detector array while increasing the \emph{scan -diameter} increases the detector array size. +For divergent beam geometries, the size of the detector array also +depends upon the \emph{focal length}. Increasing the \emph{focal +length} decreases the size of the detector array while increasing +the \emph{scan diameter} increases the detector array size. -For equiangular geometry, the detectors are spaced around a -circle covering an angular distance of -\latexonly{$\alpha$.}\latexignore{\emph{alpha}.} -The dotted circle in +For equiangular geometry, the detectors are spaced around a circle +covering an angular distance of +\latexonly{$2\,\alpha$.}\latexignore{\emph{2 \alpha}.} The dotted +circle in \begin{figure} \image{10cm;0cm}{equiangular.eps} \caption{Equiangluar geometry} @@ -275,10 +285,9 @@ figure 2.4 indicates the positions of the detectors in this case. For equilinear geometry, the detectors are space along a straight line. The length of the line depends upon -\latexonly{$\alpha$}\latexignore{\emph{alpha}} -and the \emph{focal length}. It is calculated as -\latexonly{$$\mathrm{detLengh} = 4\,f \tan (\alpha / 2)$$} -\latexignore{\\$$\emph{detLength} = 4 x F x tan(alpha/2)$$\\} +\latexonly{$\alpha$}\latexignore{\emph{alpha}} and the \emph{focal +length}. It is calculated as \latexonly{$4\,f \tan (\alpha / 2)$} +\latexignore{\emph{4 x F x tan(\alpha/2)}} \begin{figure} \image{10cm;0cm}{equilinear.eps} \caption{Equilinear geometry} @@ -320,12 +329,12 @@ transform of the projection data and multiply that by the $|w|$ filter and then perform an inverse fourier transform. Though multiplying by $|w|$ gives the sharpest reconstructions, in -practice, superior results are obtained by mutiplying the $|w|$ filter -by another filter that attenuates the higher frequencies. \ctsim\ has +practice, superior results are obtained by reducing the higher +frequencies. This is performed by mutiplying the $|w|$ filter by +another filter that attenuates the higher frequencies. \ctsim\ has multiple filters for this purpose. \subsubsection{Backprojection of filtered projections} -Backprojection is the process of ``smearing'' the filtered projections -over the reconstructing image. Various levels of interpolation can be -specified. In general, the trade-off is between quality and execution -time. +Backprojection is the process of ``smearing'' the filtered +projections over the reconstructing image. Various levels of +interpolation can be specified. diff --git a/doc/ctsim-gui.tex b/doc/ctsim-gui.tex index 420e56d..8d675de 100644 --- a/doc/ctsim-gui.tex +++ b/doc/ctsim-gui.tex @@ -1,54 +1,72 @@ -\chapter{ctsim - the Graphical User Interface}\label{ctsim}\index{ctsim}% +\chapter{The Graphical User Interface}\label{ctsim}\index{ctsim}% \setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}% \setfooter{\thepage}{}{}{}{}{\thepage}% \section{Overview} -\ctsim\ is the graphical shell for the CTSim project. It is -written using the wxLibrary for cross-platform compatibility with GTK, -Motif, and Microsoft Windows. It includes all of the functionality of -the command-line tool \ctsimtext\ as well as image processing and visualization features. +\ctsim\ is the graphical shell for the CTSim project. It utilizes +using the \urlref{wxWindows}{http://www.wxwindows.org} library for +cross-platform compatibility. The graphical shell is compatible +with Microsoft Windows, \urlref{GTK}{http://www.gtk.org}, and +\urlref{Motif}{http://www.openmotif.org} graphical environments. +This graphical includes all of the functionality of the +command-line interface \helprefn{\ctsimtext}{ctsimtext} as well as +great image processing and visualization features. -\ctsim\ can open projection files, image files, phantom definition files, and plotfiles. +\ctsim\ can open projection files, image files, phantom files, and +plotfiles. -\usage -ctsim [OPTIONS] [files to open...] +\usage \texttt{ctsim [files to open...] + +You can invoke \ctsim\ by itself on the command line, or include +any number of files that you want \ctsim\ to automatically open. + +\section{File Types Support} + +Phantom and plot files are stored as ASCII text. In contrast, +image and projection files are stored in binary format. \ctsim\ +incorporates logic so that binary files are cross-platform +compatible between both little and big endian architectures. -\section{Files Supported} \subsection{Phantom} -Phantom files are supported. Besides loading phantom files from -the disk, the Herman and Shepp-Logan phantoms are built-in to CTSim. -Phantom files can be read and stored on the disk. However, a text -editor is required to create and edit these files. - -\subsection{Image} -Image files are 2-dimensional files stored a 4-byte floating point values. -They are stored in little-endian format and \ctsim\ incorporates routines -to read and write files correctly on both big and little endian architextures. +Besides loading phantom files from the disk, the Herman and +Shepp-Logan phantoms are built-in to \ctsim. Phantom files can be +read and stored on the disk. However, a text editor is required to +create and edit these files. -Images files can be either real or complex valued. Typically, all images -are real except for images that have been processed by Fourier transforms. +\subsection{Image} +Image files are 2-dimensional files that store 4-byte floating +point values. Images files can be either real or complex valued. +Typically, all images are real except for images that have been +processed by Fourier transforms. As you might expect, +complex-valued images are twice the size of real-valued images +since both a real and imaginary component need to be store. \subsection{Projection} Projection files are created from Phantom files during the projection process. Numerous options are available for creation of the these files. \subsection{Plot} -Plot files are created by CTSim during analysis of image files. They can be -read and stored on the disk. They are stored as ASCII files for easy -cross-platform support. +Plot files are created by \ctsim\ during analysis of image files. +They can be read and stored on the disk. They are stored as ASCII +files for easy cross-platform support. \section{Phantom Menus} \subsection{Rasterize Dialog} -This creates an image file from a phantom. Technically, it converts -the phantom from a vector (infinite resolution) object into defined resolution -image. The parameters to set are: - -x-size Number of columns in image file -y-size Number of rows in image file -samples Numbers of samples taken per pixel in the x and y directions. - For example, if the nsamples is set to \texttt{3}, then for every - pixel in the image file, 9 samples (3 x 3) are averaged. +This creates an image file from a phantom. Technically, it +converts the phantom from a vector (infinite resolution) object +into a 2-dimension array of floating-point pixels. The parameters +to set are: + +\begin{twocollist} +%\twocolitemruled{\textbf{Parameter}}{\textbf{Options}} +\twocolitem{\texttt{X size}}{Number of columns in image file} +\twocolitem{\texttt{Y size}}{Number of rows in image file} +\twocolitem{\texttt{Samples per pixel}}{Numbers of samples taken +per pixel in both the x and y directions. For example, if the +\texttt{Samples per pixel} is set to \texttt{3}, then for every +pixel in the image file 9 samples (3 x 3) are averaged.} +\end{twocollist} \subsection{Projection Dialog} This creates a projection file from a phantom. @@ -56,11 +74,11 @@ This creates a projection file from a phantom. \section{Image Menus} \subsection{File - Properties} Properties of image files include -%\begin{itemize}\itemsep=0 -%\item Whether the image is real or complex valued -%\item Numeric statistics -%\item Image file labels -%\end{itemize} +\begin{itemize}\itemsep=0pt + \item Whether the image is real or complex valued + \item Numeric statistics + \item Image file labels +\end{itemize} \subsection{View} These options are for change the intensity scale for viewing the image. @@ -79,16 +97,16 @@ These commands are used for analyzing an image. \section{Projection Menus} \subsection{Process - Convert Polar Dialog}\label{convertpolardialog} The parameters are \texttt{xsize}, \texttt{ysize}, and \texttt{interpolation}. -The \texttt{xsize} and \texttt{ysize} parameters set the size of the +The \texttt{xsize} and \texttt{ysize} parameters set the size of the resulting image file. The \texttt{interpolation} parameter selects the interpolation method. Currently, the \texttt{bilinear} option provides the highest quality interpolation. \subsection{Process - Convert FFT Polar Dialog} -The paramters for this option are the same as -\helprefn{convertpolardialog}{Convert Polar Dialog}. For this command, -though, the projections are Fourier transformed prior to conversion to -polar image. +The parameters for this option are the same as +\helprefn{convertpolardialog}{Convert Polar Dialog}. For this +command, though, the projections are Fourier transformed prior to +conversion to polar image. \subsection{Reconstruct - Filtered Backprojection Dialog} This dialog sets the parameters for reconstructing an image from projections @@ -106,4 +124,3 @@ These commands set the scaling for the y-axis. \subsubsection{Set} \subsubsection{Auto} \subsubsection{Full} - diff --git a/doc/ctsim-install.tex b/doc/ctsim-install.tex index 77bf5ee..bb4a942 100644 --- a/doc/ctsim-install.tex +++ b/doc/ctsim-install.tex @@ -11,7 +11,16 @@ http://www.ctsim.org ftp://ftp.ctsim.org \end{verbatim} -It is available in Windows 95/NT/2000 and Linux GUI versions and non-GUI versions. +\section{Installing Windows Binary}\index{Installation,Windows}% + +Download the Windows executable file as helprefn{shown}{download}. +Simply execute this program to unpack \ctsim\ and begin the +installation program. \ctsim\ will then be accessible from the +\texttt{Start} Menu under the \texttt{Programs} submenu. + +\ctsim\ is compatible with Windows 98, Windows Me, Windows NT 4.0, +and Windows 2000. Due to use of the OpenGL and htmlhelp libraries, +\ctsim\ is not compatible with the stock Windows 95 system. \section{Installing Linux RPM}\index{Installation,Linux}% Download the RPM file from as \helprefn{shown}{download}. Then use @@ -21,12 +30,6 @@ the \texttt{rpm} manager program:\\ \ctsim will then be installed in the \texttt{/usr/local/bin} directory. -\section{Installing Windows Binary}\index{Installation,Windows}% - -Download the Windows executable file as helprefn{shown}{download}. -Simply execute this program to unpack \ctsim\ and begin the -installation program. - \section{Build From Sources}\label{build}\index{Installation,Build}% Refer to the INSTALL file included in the source distribution for diff --git a/doc/ctsim-textui.tex b/doc/ctsim-textui.tex index 85174f2..5a7976f 100644 --- a/doc/ctsim-textui.tex +++ b/doc/ctsim-textui.tex @@ -1,11 +1,11 @@ -\chapter{ctsimtext}\label{ctsimtext}\index{ctsimtext}% +\chapter{The Command Line Interface}\label{ctsimtext}\index{ctsimtext}% \setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}% \setfooter{\thepage}{}{}{}{}{\thepage}% -\ctsimtext\ is a master shell for all of the command-line utilities. +\ctsimtext\ is a master shell for all of the command-line utilities. \usage -\ctsimtext\ can be executed without any parameters. In that case, \ctsimtext\ +\ctsimtext\ can be executed without any parameters. In that case, \ctsimtext\ offers a command-line to enter the function-names and their parameters. The output of the command is displayed. Further commands may be given to \ctsimtext. The shell is exited by the \texttt{quit} command. \ctsimtext\ can also be called to execute a single command. This is especially useful for batch files containing multiple \ctsimtext\ commands. This is invoked by calling \par @@ -18,11 +18,11 @@ Perfoms math functions on a single image. \usage \begin{itemize}\itemsep=0pt - \item --invert - \item --log - \item --exp - \item --sqr - \item --sqrt + \item -\,-invert + \item -\,-log + \item -\,-exp + \item -\,-sqr + \item -\,-sqrt \end{itemize} \section{if2}\label{if2}\index{ctsimtext,if2}% @@ -30,12 +30,12 @@ Perfoms math functions on a two images. \usage \begin{itemize}\itemsep=0pt - \item --add - \item --sub - \item --mul - \item --comp - \item --column-plot - \item --row-plot + \item -\,-add + \item -\,-sub + \item -\,-mul + \item -\,-comp + \item -\,-column-plot + \item -\,-row-plot \end{itemize} \section{ifexport}\label{ifexport}\index{ctsimtext,ifexport}% @@ -45,29 +45,29 @@ Export an imagefile to a standard graphics file. \begin{itemize}\itemsep=0pt \item --format \begin{itemize}\itemsep=0pt - \item --pgm - \item --pgmasc - \item --png - \item --png16 + \item -\,-pgm + \item -\,-pgmasc + \item -\,-png + \item -\,-png16 \end{itemize} - \item --center + \item -\,-center \begin{itemize}\itemsep=0pt \item median \item mode \item mean \end{itemize} - \item --auto + \item -\,-auto \begin{itemize}\itemsep=0pt - \item --full - \item --std0.1 - \item --std0.5 - \item --std1 - \item --std2 - \item --std3 + \item -\,-full + \item -\,-std0.1 + \item -\,-std0.5 + \item -\,-std1 + \item -\,-std2 + \item -\,-std3 \end{itemize} - \item --scale - \item --min - \item --max + \item -\,-scale + \item -\,-min + \item -\,-max \end{itemize} \section{ifinfo}\label{ifinfo}\index{ctsimtext,ifinfo}% @@ -76,11 +76,11 @@ Displays information about an imagefile. \usage \begin{itemize}\itemsep=0pt - \item --labels - \item --no-labels - \item --stats - \item --no-stats - \item --help + \item -\,-labels + \item -\,-no-labels + \item -\,-stats + \item -\,-no-stats + \item -\,-help \end{itemize} \section{phm2pj}\label{phm2pj}\index{ctsimtext,phm2pj}% @@ -89,35 +89,35 @@ Simulates collection of X-rays data (projections) around a phantom object. \usage phm2pj projection-file-name number-of-detectors number-of-views [options...] \begin{itemize}\itemsep=0pt - \item --phantom - Select a standard phantom + \item -\,-phantom + Select a standard phantom \begin{itemize}\itemsep=0pt \item herman \item shepp-logan \item unit-pulse \end{itemize} - \item --phmfile + \item -\,-phmfile Load a phantom definition definition - \item --geometry + \item -\,-geometry \begin{itemize}\itemsep=0pt \item parallel \item equiangular \item equilinear \end{itemize} - \item --nray + \item -\,-nray Number of samples per each detector - \item --rotangle + \item -\,-rotangle Sets the rotation amount as a multiple of pi. For parallel geometries use a rotation angle of 1 and for equilinear and equiangular geometries use a rotation angle of 2. - \item --field-of-view + \item -\,-field-of-view Sets the field of view as a ratio of the diameter of the phantom. For parallel geometries, using a value of 1.0 is fine. For other geometies, this should be at least 1.3 to avoid artifacts. - \item --focal-length + \item -\,-focal-length Sets the distance of the radiation source and detectors from the center of the object as a ratio of the radius of the object. For parallel geometries, a value of 1.0 is fine. For other geometries, this should be at least 2.0 to avoid artifacts. \end{itemize} @@ -130,7 +130,7 @@ to average per pixel. \usage \begin{itemize}\itemsep=0pt - \item --nsamples + \item -\,-nsamples \end{itemize} \section{pj2if}\label{pj2if}\index{ctsimtext,pj2if}% @@ -138,7 +138,7 @@ Convert a projection file into an imagefile. \usage \begin{itemize}\itemsep=0pt -\item --help Print brief online help +\item -\,-help Print brief online help \end{itemize} \section{pjinfo}\label{pjinfo}\index{ctsimtext,pjinfo}% @@ -146,11 +146,11 @@ Displays information about a projection file. \usage \begin{itemize}\itemsep=0pt - \item --binaryheader - \item --binaryview - \item --startview - \item --endview - \item --dump + \item -\,-binaryheader + \item -\,-binaryview + \item -\,-startview + \item -\,-endview + \item -\,-dump \end{itemize} \section{pjrec}\label{pjrec}\index{ctsimtext,pjrec}% @@ -159,18 +159,23 @@ Reconstructs the interior of an object from a projection file. \usage \begin{twocollist} \twocolitemruled{\textbf{Parameter}}{\textbf{Options}} -\twocolitem{\textbf{--filter}}{Selects which filter to apply to each projection. To properly reconstruct an image, this filter should be multiplied -by the absolute value of distance from zero frequency. +\twocolitem{\textbf{-\,-filter}}{Selects which filter to apply to +each projection. To properly reconstruct an image, this filter +should be multiplied by the absolute value of distance from zero +frequency. \begin{itemize}\itemsep=0pt \item abs\_bandlimit \item abs\_cosine \item abs\_hamming \end{itemize} -} -\twocolitem{\textbf{\-\-filter-parameter}}{Sets the alpha level for Hamming +} \twocolitem{\textbf{-\,-filter-parameter}}{Sets the alpha level +for Hamming window. At setting of 0.54, this equals the Hanning window.} -\twocolitem{\textbf{\-\-filter-method}}{Selects the filtering method. For large numbers of detectors, \texttt{rfftw} is optimal. For smaller numbers of detectors, \texttt{convolution} might be a bit faster. +\twocolitem{\textbf{-\,-filter-method}}{Selects the filtering +method. For large numbers of detectors, \texttt{rfftw} is optimal. +For smaller numbers of detectors, \texttt{convolution} might be a +bit faster. \begin{itemize}\itemsep=0pt \item convolution \item fourier @@ -178,31 +183,43 @@ by the absolute value of distance from zero frequency. \item fftw \item rfftw \end{itemize} -} -\twocolitem{\textbf{\-\-filter-generation}}{Selects the filter generation. With convolution, \texttt{direct} is the proper method to select. With any of the frequency methods, \texttt{inverse-fourier} is the best method. -\begin{itemize}\itemsep=0pt -\item direct -\item inverse-fourier -\end{itemize} -} -\twocolitem{\textbf{--interpolation}}{Interpolation technique. \texttt{linear} is optimal. +} \twocolitem{\textbf{-\,-interpolation}}{Interpolation technique. +\texttt{linear} is optimal. \begin{itemize}\itemsep=0pt \item nearest \item linear +\item cubic \end{itemize} } -\twocolitem{\textbf{-backprojection}}{Selects the backprojection technique. A setting of \texttt{idiff3} is optimal. +\end{twocollist} + +\subsection{Advanced Options} + +These options are only visible if \emph{Advanced Options} has been +selected in the \texttt{File/Preferences} dialog. + +\begin{twocollist} +\twocolitem{\textbf{-\,-backprojection}}{Selects the +backprojection technique. A setting of \texttt{idiff} is optimal. \begin{itemize}\itemsep=0pt \item trig \item table \item diff -\item diff2 -\item idiff2 -\item idiff3 +\item idiff \end{itemize} } -\twocolitem{\textbf{--zeropad}}{Zeropad factor. A setting of \texttt{1} is optimal.} -\twocolitem{\textbf{--preinterpolate}}{Selects preinterpolation interpolation technique and sets the preinterpolation factor. Currently, this is experimental and does not work well.} -\end{twocollist} +\twocolitem{\textbf{-\,-zeropad}}{Zeropad factor. A setting of +\texttt{1} is optimal.} + +\twocolitem{\textbf{-\,-filter-generation}}{Selects the filter +generation. With convolution, \texttt{direct} is the proper method +to select. With any of the frequency methods, +\texttt{inverse-fourier} is the best method. +\begin{itemize}\itemsep=0pt +\item direct +\item inverse-fourier +\end{itemize} +\end{twocollist} +} diff --git a/doc/ctsim-web.tex b/doc/ctsim-web.tex index de856c5..42c2d6a 100644 --- a/doc/ctsim-web.tex +++ b/doc/ctsim-web.tex @@ -1,4 +1,4 @@ -\chapter{The Web Browser CGI Interface}\label{webinterface}\index{Web Interface}% +\chapter{The Web Interface}\label{webinterface}\index{Web Interface}% \setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}% \setfooter{\thepage}{}{}{}{}{\thepage}% diff --git a/doc/ctsim.tex b/doc/ctsim.tex index fadc1ac..73deaf4 100644 --- a/doc/ctsim.tex +++ b/doc/ctsim.tex @@ -28,14 +28,11 @@ \parskip=10pt% \parindent=0pt% %\backgroundcolour{255;255;255}\textcolour{0;0;0}% Has an effect in HTML only -\winhelpignore{\title{CTSim 3.0 User Manual}% +\title{CTSim 3.0 User Manual}% \author{Kevin Rosenberg, M.D.}% -\date{February 2001}% -}% -\winhelponly{\title{CTSim 3.0 User Manual}% -\author{by Kevin Rosenberg, M.D.\\$$\image{3cm;3cm}{logo-huge.bmp}$$}% -}% +\date{February 9, 2001}% \makeindex% + \begin{document}% \maketitle% \pagestyle{fancyplain}% @@ -43,8 +40,10 @@ \setheader{{\it CONTENTS}}{}{}{}{}{{\it CONTENTS}}% \setfooter{\thepage}{}{}{}{}{\thepage}% +\parskip=2pt \tableofcontents% +\parskip=10pt \chapter*{Copyright notice}% \setheader{{\it COPYRIGHT}}{}{}{}{}{{\it COPYRIGHT}}% \setfooter{\thepage}{}{}{}{}{\thepage}% diff --git a/doc/mytitle.sty b/doc/mytitle.sty index 5ab1d58..0a1756b 100644 --- a/doc/mytitle.sty +++ b/doc/mytitle.sty @@ -9,7 +9,7 @@ {\sf\@author} \par {\sf With documentation contributions by Ian Kay, Ph.D.}} -\vskip 1.5em {\large\sf \@date \par} \end{flushleft} \par +\vskip 3em {\large\sf Manual Version 0.2\\\@date \par} \end{flushleft} \par \@thanks \vfill {\sf\small\begin{flushright}% diff --git a/include/Makefile.am b/include/Makefile.am index 965756b..88079cc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,4 @@ -noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream_subst scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h transformmatrix.h procsignal.h reconstruct.h plotfile.h hashtable.h fourier.h ctglobals.h dlgezplot.h cubicinterp.h +noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream_subst scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h transformmatrix.h procsignal.h reconstruct.h plotfile.h hashtable.h fourier.h ctglobals.h dlgezplot.h interpolator.h diff --git a/include/backprojectors.h b/include/backprojectors.h index d9144de..8fbb06b 100644 --- a/include/backprojectors.h +++ b/include/backprojectors.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: backprojectors.h,v 1.20 2001/02/09 01:54:20 kevin Exp $ +** $Id: backprojectors.h,v 1.21 2001/02/11 04:56:37 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 @@ -45,9 +45,7 @@ class Backprojector static const int BPROJ_TRIG; static const int BPROJ_TABLE; static const int BPROJ_DIFF; - static const int BPROJ_DIFF2; - static const int BPROJ_IDIFF2; - static const int BPROJ_IDIFF3; + static const int BPROJ_IDIFF; static const int INTERP_INVALID; static const int INTERP_NEAREST; @@ -182,31 +180,11 @@ class BackprojectDiff : public Backproject double im_xinc, im_yinc; }; -class BackprojectDiff2 : public BackprojectDiff -{ - public: - BackprojectDiff2 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) - : BackprojectDiff (proj, im, interpID, interpFactor) - {} - - void BackprojectView (const double* const t, const double view_angle); -}; - -class BackprojectIntDiff2 : public BackprojectDiff -{ - public: - BackprojectIntDiff2 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) - : BackprojectDiff (proj, im, interpID, interpFactor) - {} - - void BackprojectView (const double* const t, const double view_angle); -}; - -class BackprojectIntDiff3 : public BackprojectDiff +class BackprojectIntDiff : public BackprojectDiff { public: - BackprojectIntDiff3 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) + BackprojectIntDiff (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) : BackprojectDiff (proj, im, interpID, interpFactor) {} diff --git a/include/ct.h b/include/ct.h index 25082ca..9be0e7f 100644 --- a/include/ct.h +++ b/include/ct.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ct.h,v 1.56 2001/02/08 23:08:10 kevin Exp $ +** $Id: ct.h,v 1.57 2001/02/11 04:56:37 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 @@ -164,7 +164,7 @@ extern "C" { #endif #include "ctsupport.h" -#include "cubicinterp.h" +#include "interpolator.h" #include "fnetorderstream.h" #ifdef HAVE_SGP diff --git a/include/filter.h b/include/filter.h index 0a610d6..2dd5ed5 100644 --- a/include/filter.h +++ b/include/filter.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: filter.h,v 1.24 2001/01/28 19:10:18 kevin Exp $ +** $Id: filter.h,v 1.25 2001/02/11 04:56:37 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 @@ -103,6 +103,8 @@ class SignalFilter { static void setNumIntegral(int nIntegral) {N_INTEGRAL = nIntegral;} static const int getFilterCount() {return s_iFilterCount;} + static const int getReconstructFilterCount() { return s_iReconstructFilterCount; } + static const char** getFilterNameArray() {return s_aszFilterName;} static const char** getFilterTitleArray() {return s_aszFilterTitle;} static int convertFilterNameToID (const char* const filterName); @@ -142,6 +144,7 @@ class SignalFilter { static const char* s_aszFilterName[]; static const char* s_aszFilterTitle[]; static const int s_iFilterCount; + static const int s_iReconstructFilterCount; static const char* s_aszDomainName[]; static const char* s_aszDomainTitle[]; static const int s_iDomainCount; diff --git a/libctsim/backprojectors.cpp b/libctsim/backprojectors.cpp index 8afe189..c7a8f27 100644 --- a/libctsim/backprojectors.cpp +++ b/libctsim/backprojectors.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: backprojectors.cpp,v 1.25 2001/02/09 01:54:20 kevin Exp $ +** $Id: backprojectors.cpp,v 1.26 2001/02/11 04:56:37 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 @@ -30,18 +30,14 @@ const int Backprojector::BPROJ_INVALID = -1; const int Backprojector::BPROJ_TRIG = 0; const int Backprojector::BPROJ_TABLE = 1; const int Backprojector::BPROJ_DIFF = 2; -const int Backprojector::BPROJ_DIFF2 = 3; -const int Backprojector::BPROJ_IDIFF2 = 4; -const int Backprojector::BPROJ_IDIFF3 = 5; +const int Backprojector::BPROJ_IDIFF = 3; const char* Backprojector::s_aszBackprojectName[] = { {"trig"}, {"table"}, {"diff"}, - {"diff2"}, - {"idiff2"}, - {"idiff3"}, + {"idiff"}, }; const char* Backprojector::s_aszBackprojectTitle[] = @@ -49,9 +45,7 @@ const char* Backprojector::s_aszBackprojectTitle[] = {"Direct Trigometric"}, {"Trigometric Table"}, {"Difference Iteration"}, - {"Difference Iteration Optimized"}, - {"Integer Difference Iteration Optimized"}, - {"Integer Difference Iteration Highly-Optimized"}, + {"Integer Difference Iteration"}, }; const int Backprojector::s_iBackprojectCount = sizeof(s_aszBackprojectName) / sizeof(const char*); @@ -73,7 +67,9 @@ const char* Backprojector::s_aszInterpName[] = {"nearest"}, {"linear"}, {"cubic"}, +#if HAVE_FREQ_PREINTERP {"freq_preinterpolationj"}, +#endif #if HAVE_BSPLINE_INTERP {"bspline"}, {"1bspline"}, @@ -87,7 +83,9 @@ const char* Backprojector::s_aszInterpTitle[] = {"Nearest"}, {"Linear"}, {"Cubic"}, +#if HAVE_FREQ_PREINTERP {"Frequency Preinterpolation"}, +#endif #if HAVE_BSPLINE_INTERP {"B-Spline"}, {"B-Spline 1st Order"}, @@ -162,12 +160,8 @@ Backprojector::initBackprojector (const Projections& proj, ImageFile& im, const m_pBackprojectImplem = static_cast(new BackprojectTable (proj, im, m_idInterpolation, interpFactor)); else if (m_idBackproject == BPROJ_DIFF) m_pBackprojectImplem = static_cast(new BackprojectDiff (proj, im, m_idInterpolation, interpFactor)); - else if (m_idBackproject == BPROJ_DIFF2) - m_pBackprojectImplem = static_cast(new BackprojectDiff2 (proj, im, m_idInterpolation, interpFactor)); - else if (m_idBackproject == BPROJ_IDIFF2) - m_pBackprojectImplem = static_cast(new BackprojectIntDiff2 (proj, im, m_idInterpolation, interpFactor)); - else if (m_idBackproject == BPROJ_IDIFF3) - m_pBackprojectImplem = static_cast(new BackprojectIntDiff3 (proj, im, m_idInterpolation, interpFactor)); + else if (m_idBackproject == BPROJ_IDIFF) + m_pBackprojectImplem = static_cast(new BackprojectIntDiff (proj, im, m_idInterpolation, interpFactor)); } else { m_fail = true; m_failMessage = "Unable to select a backprojection method [Backprojector::initBackprojector]"; @@ -333,9 +327,9 @@ BackprojectTrig::BackprojectView (const double* const filteredProj, const double { double theta = view_angle; - CubicInterpolator* pCubicInterp = NULL; + CubicPolyInterpolator* pCubicInterp = NULL; if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); double x = xMin + xInc / 2; // Rectang coords of center of pixel for (int ix = 0; ix < nx; x += xInc, ix++) { @@ -403,9 +397,9 @@ BackprojectTable::BackprojectView (const double* const filteredProj, const doubl { double theta = view_angle; - CubicInterpolator* pCubicInterp = NULL; + CubicPolyInterpolator* pCubicInterp = NULL; if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); for (int ix = 0; ix < nx; ix++) { ImageFileColumn pImCol = v[ix]; @@ -462,84 +456,28 @@ BackprojectDiff::~BackprojectDiff() ScaleImageByRotIncrement(); } -void -BackprojectDiff::BackprojectView (const double* const filteredProj, const double view_angle) -{ - double theta = view_angle; // add half PI to view angle to get perpendicular theta angle - double det_dx = xInc * cos (theta); - double det_dy = yInc * sin (theta); - double lColStart = start_r * cos (theta - start_phi); // calculate L for first point in image - - CubicInterpolator* pCubicInterp = NULL; - if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); - - for (int ix = 0; ix < nx; ix++, lColStart += det_dx) { - double curDetPos = lColStart; - ImageFileColumn pImCol = v[ix]; - - for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { -#ifdef DEBUG - printf ("[%2d,%2d]: %8.5f ", ix, iy, curDetPos); -#endif - if (interpType == Backprojector::INTERP_NEAREST) { - int iDetPos = iDetCenter + nearest(curDetPos / detInc); // calc index in the filtered raysum vector - - if (iDetPos >= 0 && iDetPos < nDet) - pImCol[iy] += filteredProj[iDetPos]; - } else if (interpType == Backprojector::INTERP_LINEAR) { - double detPos = curDetPos / detInc; // position along detector - double detPosFloor = floor (detPos); - int iDetPos = iDetCenter + static_cast(detPosFloor); - double frac = detPos - detPosFloor; // fraction distance from det - if (iDetPos >= 0 && iDetPos < nDet - 1) - pImCol[iy] += ((1-frac) * filteredProj[iDetPos] + frac * filteredProj[iDetPos+1]); - } else if (interpType = Backprojector::INTERP_CUBIC) { - double p = iDetCenter + (curDetPos / detInc); // position along detector - if (p >= 0 && p < nDet) - pImCol[iy] += pCubicInterp->interpolate (p); - } - } // end for y - } // end for x - - if (interpType == Backprojector::INTERP_CUBIC) - delete pCubicInterp; -} - - -// CLASS IDENTICATION -// BackprojectDiff2 -// -// PURPOSE -// Optimized version of BackprojectDiff void -BackprojectDiff2::BackprojectView (const double* const filteredProj, const double view_angle) +BackprojectDiff::BackprojectView (const double* const filteredProj, const double view_angle) { double theta = view_angle; - CubicInterpolator* pCubicInterp = NULL; - if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); - - // Distance betw. detectors for an angle given in units of detectors + // Distance between detectors for an angle given in units of detectors double det_dx = xInc * cos (theta) / detInc; double det_dy = yInc * sin (theta) / detInc; // calculate detPosition for first point in image (ix=0, iy=0) double detPosColStart = start_r * cos (theta - start_phi) / detInc; -#ifdef DEBUG - printf ("start_r=%8.5f, start_phi=%8.5f, rotScale=%8.5f\n", start_r, start_phi, rotScale); -#endif + CubicPolyInterpolator* pCubicInterp = NULL; + if (interpType == Backprojector::INTERP_CUBIC) + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); + for (int ix = 0; ix < nx; ix++, detPosColStart += det_dx) { double curDetPos = detPosColStart; ImageFileColumn pImCol = v[ix]; for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { -#ifdef DEBUG - printf ("[%2d,%2d]: %8.5f %8.5f\n", ix, iy, curDetPos, filteredProj[iDetCenter + nearest(curDetPos)]); -#endif if (interpType == Backprojector::INTERP_NEAREST) { int iDetPos = iDetCenter + nearest (curDetPos); // calc index in the filtered raysum vector @@ -563,77 +501,15 @@ BackprojectDiff2::BackprojectView (const double* const filteredProj, const doubl delete pCubicInterp; } -// CLASS IDENTICATION -// BackprojectIntDiff2 -// -// PURPOSE -// Integer version of BackprojectDiff2 - -void -BackprojectIntDiff2::BackprojectView (const double* const filteredProj, const double view_angle) -{ - double theta = view_angle; - - CubicInterpolator* pCubicInterp = NULL; - if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); - - static const kint32 scale = 1 << 16; - static const double dScale = scale; - static const kint32 halfScale = scale / 2; - - const kint32 det_dx = nearest (xInc * cos (theta) / detInc * scale); - const kint32 det_dy = nearest (yInc * sin (theta) / detInc * scale); - - // calculate L for first point in image (0, 0) - kint32 detPosColStart = nearest (start_r * cos (theta - start_phi) / detInc * scale); - - for (int ix = 0; ix < nx; ix++, detPosColStart += det_dx) { - kint32 curDetPos = detPosColStart; - ImageFileColumn pImCol = v[ix]; - - for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { - if (interpType == Backprojector::INTERP_NEAREST) { - int detPosNearest = (curDetPos >= 0 ? ((curDetPos + halfScale) / scale) : ((curDetPos - halfScale) / scale)); - int iDetPos = iDetCenter + detPosNearest; // calc index in the filtered raysum vector - - if (iDetPos < 0 || iDetPos >= nDet) // check for index outside of raysum pos - errorIndexOutsideDetector (ix, iy, theta, curDetPos, iDetPos); - else - *pImCol++ += filteredProj[iDetPos]; - } else if (interpType == Backprojector::INTERP_LINEAR) { - kint32 detPosFloor = curDetPos / scale; - kint32 detPosRemainder = curDetPos % scale; - if (detPosRemainder < 0) { - detPosFloor--; - detPosRemainder += scale; - } - int iDetPos = iDetCenter + detPosFloor; - double frac = detPosRemainder / dScale; - if (iDetPos < 0 || iDetPos >= nDet - 1) - errorIndexOutsideDetector (ix, iy, theta, curDetPos, iDetPos); - else - *pImCol++ += ((1.-frac) * filteredProj[iDetPos] + frac * filteredProj[iDetPos+1]); - } else if (interpType = Backprojector::INTERP_CUBIC) { - double p = iDetCenter + (static_cast(curDetPos) / scale); // position along detector - if (p >= 0 && p < nDet) - *pImCol++ += pCubicInterp->interpolate (p); - } - } // end for y - } // end for x - - if (interpType == Backprojector::INTERP_CUBIC) - delete pCubicInterp; -} // CLASS IDENTICATION -// BackprojectIntDiff3 +// BackprojectIntDiff // // PURPOSE -// Highly optimized version of BackprojectIntDiff2 +// Highly optimized and integer version of BackprojectDiff void -BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const double view_angle) +BackprojectIntDiff::BackprojectView (const double* const filteredProj, const double view_angle) { double theta = view_angle; // add half PI to view angle to get perpendicular theta angle static const int scaleShift = 16; @@ -649,7 +525,7 @@ BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const do kint32 detPosColStart = nearest ((start_r * cos (theta - start_phi) / detInc + iDetCenter) * scale); double* deltaFilteredProj = NULL; - CubicInterpolator* pCubicInterp = NULL; + CubicPolyInterpolator* pCubicInterp = NULL; if (interpType == Backprojector::INTERP_LINEAR) { // precalculate scaled difference for linear interpolation deltaFilteredProj = new double [nDet]; @@ -657,7 +533,7 @@ BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const do deltaFilteredProj[i] = (filteredProj[i+1] - filteredProj[i]) * dInvScale; deltaFilteredProj[nDet - 1] = 0; // last detector } else if (interpType == Backprojector::INTERP_CUBIC) { - pCubicInterp = new CubicInterpolator (filteredProj, nDet); + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); } int iLastDet = nDet - 1; @@ -688,7 +564,7 @@ BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const do for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { *pImCol++ += pCubicInterp->interpolate (static_cast(curDetPos) / 65536); } - } // end cubic + } // end Cubic } // end for ix if (interpType == Backprojector::INTERP_LINEAR) @@ -703,9 +579,9 @@ BackprojectEquiangular::BackprojectView (const double* const filteredProj, const { double beta = view_angle; - CubicInterpolator* pCubicInterp = NULL; + CubicPolyInterpolator* pCubicInterp = NULL; if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); for (int ix = 0; ix < nx; ix++) { ImageFileColumn pImCol = v[ix]; @@ -746,9 +622,9 @@ BackprojectEquilinear::BackprojectView (const double* const filteredProj, const { double beta = view_angle; - CubicInterpolator* pCubicInterp = NULL; + CubicPolyInterpolator* pCubicInterp = NULL; if (interpType == Backprojector::INTERP_CUBIC) - pCubicInterp = new CubicInterpolator (filteredProj, nDet); + pCubicInterp = new CubicPolyInterpolator (filteredProj, nDet); for (int ix = 0; ix < nx; ix++) { ImageFileColumn pImCol = v[ix]; diff --git a/libctsim/filter.cpp b/libctsim/filter.cpp index 4ac9017..f4a10f3 100644 --- a/libctsim/filter.cpp +++ b/libctsim/filter.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2000 Kevin Rosenberg ** -** $Id: filter.cpp,v 1.35 2001/01/28 19:10:18 kevin Exp $ +** $Id: filter.cpp,v 1.36 2001/02/11 04:56:37 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 @@ -30,7 +30,7 @@ int SignalFilter::N_INTEGRAL=500; //static member const int SignalFilter::FILTER_INVALID = -1 ; -const int SignalFilter::FILTER_ABS_BANDLIMIT = 0; // filter times |x = | +const int SignalFilter::FILTER_ABS_BANDLIMIT = 0; // filter times |x| const int SignalFilter::FILTER_ABS_G_HAMMING = 1; const int SignalFilter::FILTER_ABS_COSINE = 2; const int SignalFilter::FILTER_ABS_SINC = 3; @@ -41,6 +41,8 @@ const int SignalFilter::FILTER_G_HAMMING = 7; const int SignalFilter::FILTER_COSINE = 8; const int SignalFilter::FILTER_TRIANGLE = 9; +const int SignalFilter::s_iReconstructFilterCount = 5; + const char* SignalFilter::s_aszFilterName[] = { {"abs_bandlimit"}, {"abs_hamming"}, diff --git a/libctsim/procsignal.cpp b/libctsim/procsignal.cpp index 32af552..707ee38 100644 --- a/libctsim/procsignal.cpp +++ b/libctsim/procsignal.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: procsignal.cpp,v 1.24 2001/01/28 19:10:18 kevin Exp $ +** $Id: procsignal.cpp,v 1.25 2001/02/11 04:56:37 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 @@ -44,7 +44,7 @@ const int ProcessSignal::FILTER_METHOD_RFFTW =5 ; const char* ProcessSignal::s_aszFilterMethodName[] = { {"convolution"}, {"fourier"}, - {"fouier_table"}, + {"fouier-table"}, {"fft"}, #if HAVE_FFTW {"fftw"}, @@ -69,7 +69,7 @@ const int ProcessSignal::FILTER_GENERATION_DIRECT = 0; const int ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER = 1; const char* ProcessSignal::s_aszFilterGenerationName[] = { {"direct"}, - {"inverse_fourier"}, + {"inverse-fourier"}, }; const char* ProcessSignal::s_aszFilterGenerationTitle[] = { {"Direct"}, diff --git a/libctsim/reconstruct.cpp b/libctsim/reconstruct.cpp index da99f59..e80cc4f 100644 --- a/libctsim/reconstruct.cpp +++ b/libctsim/reconstruct.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: reconstruct.cpp,v 1.11 2001/01/30 05:05:41 kevin Exp $ +** $Id: reconstruct.cpp,v 1.12 2001/02/11 04:56:37 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 @@ -49,8 +49,12 @@ */ -Reconstructor::Reconstructor (const Projections& rProj, ImageFile& rIF, const char* const filterName, double filt_param, const char* const filterMethodName, const int zeropad, const char* filterGenerationName, const char* const interpName, int interpFactor, const char* const backprojectName, const int iTrace, SGP* pSGP) - : m_rProj(rProj), m_rImagefile(rIF), m_pProcessSignal(0), m_pBackprojector(0), m_iTrace(iTrace), m_bFail(false), m_adPlotXAxis(0) +Reconstructor::Reconstructor (const Projections& rProj, ImageFile& rIF, const char* const filterName, + double filt_param, const char* const filterMethodName, const int zeropad, + const char* filterGenerationName, const char* const interpName, + int interpFactor, const char* const backprojectName, const int iTrace, SGP* pSGP) + : m_rProj(rProj), m_rImagefile(rIF), m_pProcessSignal(0), m_pBackprojector(0), m_iTrace(iTrace), + m_bFail(false), m_adPlotXAxis(0) { m_nFilteredProjections = m_rProj.nDet() * interpFactor; @@ -65,7 +69,9 @@ Reconstructor::Reconstructor (const Projections& rProj, ImageFile& rIF, const ch #endif double filterBW = 1. / m_rProj.detInc(); - m_pProcessSignal = new ProcessSignal (filterName, filterMethodName, filterBW, m_rProj.detInc(), m_rProj.nDet(), filt_param, "spatial", filterGenerationName, zeropad, interpFactor, iTrace, m_rProj.geometry(), m_rProj.focalLength(), pSGP); + m_pProcessSignal = new ProcessSignal (filterName, filterMethodName, filterBW, m_rProj.detInc(), + m_rProj.nDet(), filt_param, "spatial", filterGenerationName, zeropad, interpFactor, iTrace, + m_rProj.geometry(), m_rProj.focalLength(), pSGP); if (m_pProcessSignal->fail()) { m_bFail = true; diff --git a/libctsupport/Makefile.am b/libctsupport/Makefile.am index 308f252..9f279ec 100644 --- a/libctsupport/Makefile.am +++ b/libctsupport/Makefile.am @@ -1,6 +1,6 @@ noinst_LIBRARIES = libctsupport.a INCLUDES=@my_includes@ -libctsupport_a_SOURCES= strfuncs.cpp syserror.cpp fnetorderstream.cpp consoleio.cpp mathfuncs.cpp xform.cpp clip.cpp plotfile.cpp hashtable.cpp cubicinterp.cpp +libctsupport_a_SOURCES= strfuncs.cpp syserror.cpp fnetorderstream.cpp consoleio.cpp mathfuncs.cpp xform.cpp clip.cpp plotfile.cpp hashtable.cpp interpolator.cpp EXTRA_DIST=Makefile.nt diff --git a/msvc/ctsim/ctsim.plg b/msvc/ctsim/ctsim.plg index ae08e1e..d9390b5 100644 --- a/msvc/ctsim/ctsim.plg +++ b/msvc/ctsim/ctsim.plg @@ -6,15 +6,15 @@ --------------------Configuration: ctsim - Win32 Debug--------------------

Command Lines

-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP49.tmp" with contents +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP299.tmp" with contents [ /nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "\wx2.2.5\include" /I "..\..\..\fftw-2.1.3\fftw" /I "\wx2.2.5\src\png" /I "\wx2.2.5\src\zlib" /I "..\..\include" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\rfftw" /D VERSION=\"3.0.0beta1\" /D "_DEBUG" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D CTSIMVERSION=\"3.0.0alpha5\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c -"D:\ctsim\src\ctsim.cpp" +"C:\ctsim\src\dialogs.cpp" ] -Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP49.tmp" -Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP4A.tmp" with contents +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP299.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29A.tmp" with contents [ -comctl32.lib winmm.lib rpcrt4.lib ws2_32.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 ../libctsim/Debug/libctsim.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 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 opengl32.lib glu32.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" +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 /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" .\Debug\ctsim.obj .\Debug\dialogs.obj .\Debug\dlgprojections.obj @@ -33,10 +33,10 @@ comctl32.lib winmm.lib rpcrt4.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib w \wx2.2.5\lib\zlibd.lib \wx2.2.5\lib\tiffd.lib ] -Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP4A.tmp" +Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29A.tmp"

Output Window

Compiling... -ctsim.cpp +dialogs.cpp Linking... diff --git a/src/ctsim.cpp b/src/ctsim.cpp index a2fede7..b08db82 100644 --- a/src/ctsim.cpp +++ b/src/ctsim.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ctsim.cpp,v 1.73 2001/02/09 22:22:04 kevin Exp $ +** $Id: ctsim.cpp,v 1.74 2001/02/11 04:56:38 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 @@ -43,6 +43,7 @@ #include "wx/image.h" #include "wx/filesys.h" #include "wx/fs_zip.h" +#include "wx/msw/helpchm.h" #if !wxUSE_DOC_VIEW_ARCHITECTURE #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! @@ -70,7 +71,7 @@ #endif #endif -static const char* rcsindent = "$Id: ctsim.cpp,v 1.73 2001/02/09 22:22:04 kevin Exp $"; +static const char* rcsindent = "$Id: ctsim.cpp,v 1.74 2001/02/11 04:56:38 kevin Exp $"; struct option CTSimApp::ctsimOptions[] = { @@ -82,7 +83,7 @@ struct option CTSimApp::ctsimOptions[] = IMPLEMENT_APP(CTSimApp) CTSimApp::CTSimApp() -: m_docManager(NULL), m_pFrame(NULL), m_pLog(0), m_pLogDoc(0) +: m_docManager(NULL), m_pFrame(NULL), m_pLog(0), m_pLogDoc(0), m_bAdvancedOptions(false) { theApp = this; } @@ -262,6 +263,7 @@ IMPLEMENT_CLASS(MainFrame, wxDocParentFrame) BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame) #endif +EVT_MENU(MAINMENU_FILE_PREFERENCES, MainFrame::OnPreferences) EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout) EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents) EVT_MENU(MAINMENU_HELP_TOPICS, MainFrame::OnHelpTopics) @@ -317,6 +319,7 @@ MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O"); file_menu->AppendSeparator(); + file_menu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); file_menu->Append(MAINMENU_FILE_EXIT, "E&xit"); // history of files visited @@ -521,12 +524,6 @@ MainFrame::OnHelpSecondary (wxCommandEvent& event) void MainFrame::showHelp (int commandID) { -#ifdef CTSIM_WINHELP - m_winHelp.LoadFile(); -#else - m_htmlHelp.LoadFile(); -#endif - switch (commandID) { case MAINMENU_HELP_CONTENTS: @@ -766,6 +763,13 @@ BitmapDialog::~BitmapDialog() {} +void +MainFrame::OnPreferences (wxCommandEvent& WXUNUSED(event) ) +{ + theApp->setAdvancedOptions (! theApp->getAdvancedOptions()); +} + + #include "./splash.xpm" void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) diff --git a/src/ctsim.h b/src/ctsim.h index 63316b4..c878803 100644 --- a/src/ctsim.h +++ b/src/ctsim.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ctsim.h,v 1.42 2001/02/06 06:57:46 kevin Exp $ +** $Id: ctsim.h,v 1.43 2001/02/11 04:56:38 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 @@ -39,6 +39,7 @@ #include "wx/wx.h" #endif #include "wx/config.h" +#include "wx/msw/helpchm.h" #ifdef MSVC #define CTSIM_MDI 1 @@ -108,7 +109,7 @@ private: bool m_bShuttingDown; #if CTSIM_WINHELP - wxWinHelpController m_winHelp; + wxCHMHelpController m_winHelp; #endif wxHtmlHelpController m_htmlHelp; @@ -122,7 +123,7 @@ public: void OnSize (wxSizeEvent& event); #if CTSIM_WINHELP - wxWinHelpController& getWinHelpController() + wxCHMHelpController& getWinHelpController() {return m_winHelp; } #endif wxHtmlHelpController& getHtmlHelpController() @@ -134,6 +135,7 @@ public: void OnHelpTopics (wxCommandEvent& event); void OnHelpContents (wxCommandEvent& event); void OnCreatePhantom (wxCommandEvent& event); + void OnPreferences (wxCommandEvent& event); #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG)) void OnHelpSecondary (wxCommandEvent& event); @@ -177,7 +179,8 @@ class CTSimApp: public wxApp private: enum { O_HELP, O_VERSION }; static struct option ctsimOptions[]; - + + bool m_bAdvancedOptions; wxDocManager* m_docManager; MainFrame* m_pFrame; wxConfig* m_pConfig; @@ -214,7 +217,9 @@ public: { return new EZPlotDialog (m_pFrame); } void getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector& vecIF); - + bool getAdvancedOptions() const { return m_bAdvancedOptions; } + void setAdvancedOptions (bool bAdv) { m_bAdvancedOptions = bAdv; } + void setIconForFrame (wxFrame* pFrame); wxConfig* getConfig() { return m_pConfig; } @@ -255,6 +260,7 @@ enum { MAINMENU_FILE_CREATE_FILTER, MAINMENU_FILE_EXIT, + MAINMENU_FILE_PREFERENCES, PJMENU_FILE_PROPERTIES, PJMENU_RECONSTRUCT_FBP, diff --git a/src/dialogs.cpp b/src/dialogs.cpp index c120591..0afae26 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: dialogs.cpp,v 1.28 2001/02/08 06:25:07 kevin Exp $ +** $Id: dialogs.cpp,v 1.29 2001/02/11 04:56:38 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 @@ -508,11 +508,13 @@ DialogGetProjectionParameters::DialogGetProjectionParameters m_pTextCtrlNSamples = new wxTextCtrl (this, -1, osNSamples.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); pGridSizer->Add (new wxStaticText (this, -1, "Samples per Detector"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlNSamples, 0, wxALIGN_CENTER_VERTICAL); - std::ostringstream osRotAngle; - osRotAngle << dDefaultRotAngle; - m_pTextCtrlRotAngle = new wxTextCtrl (this, -1, osRotAngle.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - pGridSizer->Add (new wxStaticText (this, -1, "Rotation Angle (PI units)"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlRotAngle, 0, wxALIGN_CENTER_VERTICAL); + if (theApp->getAdvancedOptions()) { + std::ostringstream osRotAngle; + osRotAngle << dDefaultRotAngle; + m_pTextCtrlRotAngle = new wxTextCtrl (this, -1, osRotAngle.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + pGridSizer->Add (new wxStaticText (this, -1, "Rotation Angle (PI units)"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlRotAngle, 0, wxALIGN_CENTER_VERTICAL); + } std::ostringstream osFocalLength; osFocalLength << dDefaultFocalLength; m_pTextCtrlFocalLength = new wxTextCtrl (this, -1, osFocalLength.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); @@ -594,12 +596,20 @@ DialogGetProjectionParameters::getNSamples () double DialogGetProjectionParameters::getRotAngle () { - wxString strCtrl = m_pTextCtrlRotAngle->GetValue(); - double dValue; - if (strCtrl.ToDouble (&dValue)) - return (dValue * PI); - else - return (m_dDefaultRotAngle); + if (theApp->getAdvancedOptions()) { + wxString strCtrl = m_pTextCtrlRotAngle->GetValue(); + double dValue; + if (strCtrl.ToDouble (&dValue)) + return (dValue * PI); + else + return (m_dDefaultRotAngle); + } else { + if (Scanner::convertGeometryNameToID (m_pListBoxGeometry->getSelectionStringValue()) == + Scanner::GEOMETRY_PARALLEL) + return (PI); + else + return (2 * PI); + } } double @@ -656,7 +666,10 @@ DialogGetProjectionParameters::getTrace () ///////////////////////////////////////////////////////////////////// -DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxWindow* pParent, int iDefaultXSize, int iDefaultYSize, int iDefaultFilterID, double dDefaultFilterParam, int iDefaultFilterMethodID, int iDefaultFilterGenerationID, int iDefaultZeropad, int iDefaultInterpID, int iDefaultInterpParam, int iDefaultBackprojectID, int iTrace) +DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxWindow* pParent, int iDefaultXSize, + int iDefaultYSize, int iDefaultFilterID, double dDefaultFilterParam, + int iDefaultFilterMethodID, int iDefaultFilterGenerationID, int iDefaultZeropad, + int iDefaultInterpID, int iDefaultInterpParam, int iDefaultBackprojectID, int iTrace) : wxDialog (pParent, -1, "Set Reconstruction Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) { wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); @@ -665,25 +678,13 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxWindow* pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); - std::ostringstream os; - os << iDefaultXSize; - m_pTextCtrlXSize = new wxTextCtrl (this, -1, os.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - std::ostringstream osYSize; - osYSize << iDefaultYSize; - m_pTextCtrlYSize = new wxTextCtrl (this, -1, osYSize.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - std::ostringstream osFilterParam; - osFilterParam << dDefaultFilterParam; - m_pTextCtrlFilterParam = new wxTextCtrl (this, -1, osFilterParam.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - std::ostringstream osZeropad; - osZeropad << iDefaultZeropad; - m_pTextCtrlZeropad = new wxTextCtrl (this, -1, osZeropad.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - std::ostringstream osInterpParam; - osInterpParam << iDefaultInterpParam; - m_pTextCtrlInterpParam = new wxTextCtrl (this, -1, osInterpParam.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); - wxFlexGridSizer* pGridSizer = new wxFlexGridSizer (6); pGridSizer->Add (new wxStaticText (this, -1, "Filter"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); - m_pListBoxFilter = new StringValueAndTitleListBox (this, SignalFilter::getFilterCount(), SignalFilter::getFilterTitleArray(), SignalFilter::getFilterNameArray()); + + if (theApp->getAdvancedOptions()) + m_pListBoxFilter = new StringValueAndTitleListBox (this, SignalFilter::getFilterCount(), SignalFilter::getFilterTitleArray(), SignalFilter::getFilterNameArray()); + else + m_pListBoxFilter = new StringValueAndTitleListBox (this, SignalFilter::getReconstructFilterCount(), SignalFilter::getFilterTitleArray(), SignalFilter::getFilterNameArray()); m_pListBoxFilter->SetSelection (iDefaultFilterID); pGridSizer->Add (m_pListBoxFilter, 0, wxALL | wxALIGN_LEFT | wxEXPAND); @@ -692,17 +693,18 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxWindow* pGridSizer->Add (new wxStaticText (this, -1, "Filter Method"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); pGridSizer->Add (m_pListBoxFilterMethod, 0, wxALL | wxALIGN_LEFT | wxEXPAND); - m_pListBoxFilterGeneration = new StringValueAndTitleListBox (this, ProcessSignal::getFilterGenerationCount(), ProcessSignal::getFilterGenerationTitleArray(), ProcessSignal::getFilterGenerationNameArray()); - m_pListBoxFilterGeneration->SetSelection (iDefaultFilterGenerationID); - pGridSizer->Add (new wxStaticText (this, -1, "Filter Generation"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); - pGridSizer->Add (m_pListBoxFilterGeneration, 0, wxALL | wxALIGN_LEFT | wxEXPAND); - - - m_pListBoxBackproject = new StringValueAndTitleListBox (this, Backprojector::getBackprojectCount(), Backprojector::getBackprojectTitleArray(), Backprojector::getBackprojectNameArray()); - m_pListBoxBackproject->SetSelection (iDefaultBackprojectID); - pGridSizer->Add (new wxStaticText (this, -1, "Backprojection"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); - pGridSizer->Add (m_pListBoxBackproject, 0, wxALL | wxALIGN_RIGHT | wxEXPAND); + if (theApp->getAdvancedOptions()) { + m_pListBoxFilterGeneration = new StringValueAndTitleListBox (this, ProcessSignal::getFilterGenerationCount(), ProcessSignal::getFilterGenerationTitleArray(), ProcessSignal::getFilterGenerationNameArray()); + m_pListBoxFilterGeneration->SetSelection (iDefaultFilterGenerationID); + pGridSizer->Add (new wxStaticText (this, -1, "Filter Generation"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pGridSizer->Add (m_pListBoxFilterGeneration, 0, wxALL | wxALIGN_LEFT | wxEXPAND); + m_pListBoxBackproject = new StringValueAndTitleListBox (this, Backprojector::getBackprojectCount(), Backprojector::getBackprojectTitleArray(), Backprojector::getBackprojectNameArray()); + m_pListBoxBackproject->SetSelection (iDefaultBackprojectID); + pGridSizer->Add (new wxStaticText (this, -1, "Backprojection"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); + pGridSizer->Add (m_pListBoxBackproject, 0, wxALL | wxALIGN_RIGHT | wxEXPAND); + } + m_pListBoxInterp = new StringValueAndTitleListBox (this, Backprojector::getInterpCount(), Backprojector::getInterpTitleArray(), Backprojector::getInterpNameArray()); m_pListBoxInterp->SetSelection (iDefaultInterpID); pGridSizer->Add (new wxStaticText (this, -1, "Interpolation"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); @@ -717,16 +719,37 @@ DialogGetReconstructionParameters::DialogGetReconstructionParameters (wxWindow* m_pListBoxTrace->SetSelection (iTrace); pGridSizer->Add (m_pListBoxTrace); + std::ostringstream osHammingParam; + osHammingParam << dDefaultFilterParam; + m_pTextCtrlFilterParam = new wxTextCtrl (this, -1, osHammingParam.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + pGridSizer->Add (new wxStaticText (this, -1, "Hamming Parameter"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlFilterParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + std::ostringstream os; + os << iDefaultXSize; + m_pTextCtrlXSize = new wxTextCtrl (this, -1, os.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); pGridSizer->Add (new wxStaticText (this, -1, "X Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlXSize, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + std::ostringstream osYSize; + osYSize << iDefaultYSize; + m_pTextCtrlYSize = new wxTextCtrl (this, -1, osYSize.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); pGridSizer->Add (new wxStaticText (this, -1, "Y Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlYSize, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (new wxStaticText (this, -1, "Filter Parameter"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlFilterParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (new wxStaticText (this, -1, "Zeropad"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); - pGridSizer->Add (m_pTextCtrlZeropad, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + + if (theApp->getAdvancedOptions()) { + std::ostringstream osZeropad; + osZeropad << iDefaultZeropad; + m_pTextCtrlZeropad = new wxTextCtrl (this, -1, osZeropad.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + pGridSizer->Add (new wxStaticText (this, -1, "Zeropad"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlZeropad, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + } + +#if HAVE_FREQ_PREINTERP + std::ostringstream osInterpParam; + osInterpParam << iDefaultInterpParam; + m_pTextCtrlInterpParam = new wxTextCtrl (this, -1, osInterpParam.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); pGridSizer->Add (new wxStaticText (this, -1, "Interpolation Parameter"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlInterpParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); +#endif pTopSizer->Add (pGridSizer, 1, wxALL, 3); @@ -777,24 +800,31 @@ DialogGetReconstructionParameters::getYSize () unsigned int DialogGetReconstructionParameters::getZeropad () { - wxString strCtrl = m_pTextCtrlZeropad->GetValue(); - unsigned long lValue; - if (strCtrl.ToULong (&lValue)) - return lValue; - else - return (m_iDefaultZeropad); + if (theApp->getAdvancedOptions()) { + wxString strCtrl = m_pTextCtrlZeropad->GetValue(); + unsigned long lValue; + if (strCtrl.ToULong (&lValue)) + return lValue; + else + return (m_iDefaultZeropad); + } else + return 1; } unsigned int DialogGetReconstructionParameters::getInterpParam () { +#if HAVE_FREQ_PREINTERP wxString strCtrl = m_pTextCtrlInterpParam->GetValue(); unsigned long lValue; if (strCtrl.ToULong (&lValue)) return lValue; else return (m_iDefaultInterpParam); +#else + return 1; +#endif } double @@ -838,13 +868,24 @@ DialogGetReconstructionParameters::getTrace () const char* DialogGetReconstructionParameters::getBackprojectName () { - return m_pListBoxBackproject->getSelectionStringValue(); + if (theApp->getAdvancedOptions()) { + return m_pListBoxBackproject->getSelectionStringValue(); + } else + return "idiff"; } const char* DialogGetReconstructionParameters::getFilterGenerationName () { - return m_pListBoxFilterGeneration->getSelectionStringValue(); + if (theApp->getAdvancedOptions()) { + return m_pListBoxFilterGeneration->getSelectionStringValue(); + } else { + if (ProcessSignal::convertFilterMethodNameToID(m_pListBoxFilterMethod->getSelectionStringValue()) + == ProcessSignal::FILTER_METHOD_CONVOLUTION) + return "direct"; + else + return "inverse-fourier"; + } } diff --git a/src/dialogs.h b/src/dialogs.h index 0284924..8311bb2 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: dialogs.h,v 1.23 2001/02/08 06:25:07 kevin Exp $ +** $Id: dialogs.h,v 1.24 2001/02/11 04:56:38 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 @@ -179,7 +179,13 @@ class DialogGetProjectionParameters : public wxDialog class DialogGetReconstructionParameters : public wxDialog { public: - DialogGetReconstructionParameters (wxWindow* pParent, int iDefaultXSize = 0, int iDefaultYSize = 0, int iDefaultFilterID = SignalFilter::FILTER_ABS_BANDLIMIT, double dDefaultFilterParam = 1., int iDefaultFilterMethodID = ProcessSignal::FILTER_METHOD_CONVOLUTION, int iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVALID, int iDefaultZeropad = 3, int iDefaultInterpID = Backprojector::INTERP_LINEAR, int iDefaultInterpParam = 1, int iDefaultBackprojectID = Backprojector::BPROJ_IDIFF3, int iDefaultTrace = Trace::TRACE_NONE); + DialogGetReconstructionParameters (wxWindow* pParent, int iDefaultXSize = 0, int iDefaultYSize = 0, + int iDefaultFilterID = SignalFilter::FILTER_ABS_BANDLIMIT, double dDefaultFilterParam = 1., + int iDefaultFilterMethodID = ProcessSignal::FILTER_METHOD_CONVOLUTION, + int iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT, + int iDefaultZeropad = 3, int iDefaultInterpID = Backprojector::INTERP_LINEAR, + int iDefaultInterpParam = 1, int iDefaultBackprojectID = Backprojector::BPROJ_IDIFF, + int iDefaultTrace = Trace::TRACE_NONE); virtual ~DialogGetReconstructionParameters (); unsigned int getXSize(); diff --git a/src/views.cpp b/src/views.cpp index 6a77ba3..ce66ec1 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: views.cpp,v 1.101 2001/02/09 14:34:16 kevin Exp $ +** $Id: views.cpp,v 1.102 2001/02/11 04:56:38 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 @@ -822,6 +822,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_PREVIEW, "Print Preview"); #ifdef CTSIM_MDI m_pFileMenu->AppendSeparator(); + m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit"); #endif GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu); @@ -2046,6 +2047,7 @@ PhantomFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view"); #ifdef CTSIM_MDI m_pFileMenu->AppendSeparator(); + m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit"); #endif GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu); @@ -2220,7 +2222,7 @@ ProjectionFileView::ProjectionFileView() m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT; #endif m_iDefaultZeropad = 1; - m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF3; + m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF; m_iDefaultInterpolation = Backprojector::INTERP_LINEAR; m_iDefaultInterpParam = 1; m_iDefaultTrace = Trace::TRACE_NONE; @@ -2325,7 +2327,10 @@ ProjectionFileView::OnReconstructFourier (wxCommandEvent& event) void ProjectionFileView::OnReconstructFBP (wxCommandEvent& event) { - DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY, m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, m_iDefaultTrace); + DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY, + m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, + m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, + m_iDefaultTrace); int retVal = dialogReconstruction.ShowModal(); if (retVal == wxID_OK) { @@ -2454,6 +2459,7 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view"); #ifdef CTSIM_MDI m_pFileMenu->AppendSeparator(); + m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit"); #endif GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu); @@ -2784,6 +2790,7 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view"); #ifdef CTSIM_MDI m_pFileMenu->AppendSeparator(); + m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit"); #endif GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu); @@ -3041,6 +3048,7 @@ TextFileView::CreateChildFrame (wxDocument *doc, wxView *view) m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view"); #ifdef CTSIM_MDI m_pFileMenu->AppendSeparator(); + m_pFileMenu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences..."); m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit"); #endif GetDocumentManager()->FileHistoryAddFilesToMenu(m_pFileMenu); diff --git a/tools/phm2pj.cpp b/tools/phm2pj.cpp index f32f5c5..687c290 100644 --- a/tools/phm2pj.cpp +++ b/tools/phm2pj.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2pj.cpp,v 1.24 2001/02/08 06:25:07 kevin Exp $ +** $Id: phm2pj.cpp,v 1.25 2001/02/11 04:56:38 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 @@ -51,7 +51,7 @@ static struct option phm2pj_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.24 2001/02/08 06:25:07 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.25 2001/02/11 04:56:38 kevin Exp $"; void @@ -72,7 +72,7 @@ phm2pj_usage (const char *program) std::cout << " --desc Description of raysum\n"; std::cout << " --nray Number of rays per detector (default = 1)\n"; std::cout << " --rotangle Degrees to rotate view through (multiple of PI)\n"; - std::cout << " (default = 1)\n"; + std::cout << " (default = select appropriate for geometry)\n"; std::cout << " --geometry Geometry of scanning\n"; std::cout << " parallel Parallel scan beams (default)\n"; std::cout << " equilinear Equilinear divergent scan beams\n"; @@ -118,7 +118,7 @@ phm2pj_main (int argc, char* const argv[]) int opt_trace = Trace::TRACE_NONE; int opt_verbose = 0; int opt_debug = 0; - double opt_rotangle = 1; + double opt_rotangle = -1; char* endptr = NULL; char* endstr; @@ -251,6 +251,13 @@ phm2pj_main (int argc, char* const argv[]) return (1); } + if (opt_rotangle < 0) { + if (optGeometryName.compare ("parallel") == 0) + opt_rotangle = 1; + else + opt_rotangle = 2; + } + std::ostringstream desc; desc << "phm2pj: NDet=" << opt_ndet << ", Nview=" << opt_nview << ", NRay=" << opt_nray << ", RotAngle=" << opt_rotangle << ", Geometry=" << optGeometryName << ", "; if (optPhmFileName.length()) { -- 2.34.1