From: Kevin M. Rosenberg Date: Fri, 25 Aug 2000 15:59:13 +0000 (+0000) Subject: r184: *** empty log message *** X-Git-Tag: debian-4.5.3-3~833 X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=commitdiff_plain;h=1e88cf0f7fa4f690ea9f110e8ed3f2b5338d0a10 r184: *** empty log message *** --- diff --git a/ChangeLog b/ChangeLog index 465d37e..9c6984f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2.0.0-b10 - 8/31/00 + ctsim: Added Auto Scaling for image windows + ctsim: Change title from "windowing" to "display scaling" + Added FieldOfView and FocalLength ratio parameters to projection collection + Changed name of Rowland Phantom to correct name of Shepp-Logan + Added data collection for equilinear scanner geometry + Fixed bug in backprojection selection + Improved projection collection animation + 2.0.0-b9 - 8/22/00 Added RCS Id strings to executable files Added RPM Spec file for RPM package creation diff --git a/configure b/configure index 79e9cb6..b46197c 100755 --- a/configure +++ b/configure @@ -712,7 +712,7 @@ fi PACKAGE=ctsim -VERSION=2.0.0b9 +VERSION=2.0.0b10 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } diff --git a/configure.in b/configure.in index 3998126..09d8ec9 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Must reset CDPATH so that bash's cd does not print to stdout dnl CDPATH= AC_INIT(src/ctsim.cpp) -AM_INIT_AUTOMAKE(ctsim,2.0.0b9) +AM_INIT_AUTOMAKE(ctsim,2.0.0b10) AM_CONFIG_HEADER(config.h) dnl Checks for programs. diff --git a/include/backprojectors.h b/include/backprojectors.h index ac609da..1781fe1 100644 --- a/include/backprojectors.h +++ b/include/backprojectors.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: backprojectors.h,v 1.12 2000/07/22 15:45:33 kevin Exp $ +** $Id: backprojectors.h,v 1.13 2000/08/25 15:59:13 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 @@ -143,7 +143,7 @@ class BackprojectTrig : public Backproject { public: BackprojectTrig (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) - : Backproject::Backproject (proj, im, interpType, interpFactor) + : Backproject::Backproject (proj, im, interpID, interpFactor) {} void BackprojectView (const double* const t, double view_angle); @@ -184,7 +184,7 @@ class BackprojectDiff2 : public BackprojectDiff { public: BackprojectDiff2 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) - : BackprojectDiff::BackprojectDiff (proj, im, interpType, interpFactor) + : BackprojectDiff::BackprojectDiff (proj, im, interpID, interpFactor) {} void BackprojectView (const double* const t, double view_angle); @@ -194,7 +194,7 @@ class BackprojectIntDiff2 : public BackprojectDiff { public: BackprojectIntDiff2 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) - : BackprojectDiff::BackprojectDiff (proj, im, interpType, interpFactor) + : BackprojectDiff::BackprojectDiff (proj, im, interpID, interpFactor) {} void BackprojectView (const double* const t, double view_angle); @@ -204,8 +204,8 @@ class BackprojectIntDiff2 : public BackprojectDiff class BackprojectIntDiff3 : public BackprojectDiff { public: - BackprojectIntDiff3 (const Projections& proj, ImageFile& im, int interpType, const int interpFactor) - : BackprojectDiff::BackprojectDiff (proj, im, interpType, interpFactor) + BackprojectIntDiff3 (const Projections& proj, ImageFile& im, int interpID, const int interpFactor) + : BackprojectDiff::BackprojectDiff (proj, im, interpID, interpFactor) {} void BackprojectView (const double* const t, double view_angle); diff --git a/include/phantom.h b/include/phantom.h index a4f29f2..56a8007 100644 --- a/include/phantom.h +++ b/include/phantom.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.h,v 1.12 2000/07/31 14:48:35 kevin Exp $ +** $Id: phantom.h,v 1.13 2000/08/25 15:59:13 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 @@ -134,9 +134,9 @@ class Phantom public: static const int PHM_INVALID; static const int PHM_HERMAN; - static const int PHM_BHERMAN; - static const int PHM_ROWLAND; - static const int PHM_BROWLAND; + static const int PHM_B_HERMAN; + static const int PHM_SHEPP_LOGAN; + static const int PHM_B_SHEPP_LOGAN; static const int PHM_UNITPULSE; Phantom (); @@ -177,8 +177,8 @@ class Phantom void addStdHerman (); void addStdHermanBordered (); - void addStdRowland (); - void addStdRowlandBordered (); + void addStdSheppLogan (); + void addStdSheppLoganBordered (); void print () const; diff --git a/include/scanner.h b/include/scanner.h index 550573a..79eee68 100644 --- a/include/scanner.h +++ b/include/scanner.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: scanner.h,v 1.11 2000/08/02 18:06:00 kevin Exp $ +** $Id: scanner.h,v 1.12 2000/08/25 15:59:13 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -74,10 +74,12 @@ class Scanner static const int Scanner::GEOMETRY_EQUIANGULAR; - Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen); + Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen, double dFieldOfView, double dFocalLength); ~Scanner(); - void collectProjections (Projections& proj, const Phantom& phm, const int start_view = 0, const int trace = TRACE_NONE, SGP* pSGP = NULL); + void collectProjections (Projections& proj, const Phantom& phm, const int trace = TRACE_NONE, SGP* pSGP = NULL); + + void collectProjections (Projections& proj, const Phantom& phm, const int iStartView, const int iNumViews, bool bStoreAtViewPosition, const int trace = TRACE_NONE, SGP* pSGP = NULL); void setNView (int nView); @@ -88,7 +90,7 @@ class Scanner const double phmLen(void) const {return m_phmLen;} const double rotInc(void) const {return m_rotInc;} const double detInc(void) const {return m_detInc;} - const double radius(void) const {return m_radius;} + const double detLen(void) const {return m_detLen;} static const int getGeometryCount() {return s_iGeometryCount;} static const char** getGeometryNameArray() {return s_aszGeometryName;} @@ -104,12 +106,13 @@ class Scanner unsigned int m_nDet; /* Number of detectors in array */ unsigned int m_nView; /* Number of rotated views */ unsigned int m_nSample; /* Number of rays per detector */ - double m_detLen; /* Total length of detector array */ - double m_rotLen; /* Rotation angle length in radians (norm 2PI) */ - double m_detInc; /* Increment between centers of detectors */ - double m_rotInc; /* Increment in rotation angle between views */ - double m_radius; /* Radius of rotation. Distance from center of phm to center of det */ - double m_phmLen; /* Maximum Length of phantom or area of interest */ + double m_dFieldOfView; // Field of View + double m_dFocalLength; // Focal Length + double m_detLen; // Total length of detector array + double m_rotLen; // Rotation angle length in radians (norm 2PI) + double m_detInc; // Increment between centers of detectors + double m_rotInc; // Increment in rotation angle between views + double m_phmLen; // Maximum Length of phantom or area of interest int m_trace; struct { double xd1,yd1,xd2,yd2; /* Coordinates of detector endpoints */ @@ -120,7 +123,6 @@ class Scanner static const char* s_aszGeometryName[]; static const char* s_aszGeometryTitle[]; static const int s_iGeometryCount; - static const int N_EXTRA_DETECTORS=0; // Number of extra detectors widths when calculating detlen void projectSingleView (const Phantom& phm, DetectorArray& darray, const double xd1, const double yd1, const double xd2, const double yd2, const double xs1, const double ys1, const double xs2, const double ys2, SGP* pSGP); @@ -128,7 +130,7 @@ class Scanner double projectLineAgainstPElem (const PhantomElement& pelem, const double x1, const double y1, const double x2, const double y2, SGP* pSGP); - void traceShowParam (const char *label, const char *fmt, int row, int color, ...); + void traceShowParam (SGP* pSGP, const char *label, const char *fmt, int row, int color, ...); }; diff --git a/include/sgp.h b/include/sgp.h index 7cda247..6240752 100644 --- a/include/sgp.h +++ b/include/sgp.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.h,v 1.13 2000/08/02 18:06:00 kevin Exp $ +** $Id: sgp.h,v 1.14 2000/08/25 15:59:13 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 @@ -137,6 +137,10 @@ private: static RGBColor s_aRGBColor[]; static int s_iRGBColorCount; +#if HAVE_WXWINDOWS + wxPen* m_pPen; +#endif + public: enum { // linestyles LS_NOLINE = 0, diff --git a/include/trace.h b/include/trace.h index 88aa271..64826e9 100644 --- a/include/trace.h +++ b/include/trace.h @@ -1,15 +1,13 @@ #ifndef TRACE_H #define TRACE_H -enum TraceID { - TRACE_INVALID=-1, - TRACE_NONE=0, /* No tracing */ - TRACE_TEXT, /* Minimal status */ - TRACE_PHM, /* Show phantom */ - TRACE_RAYS, /* Show all rays */ - TRACE_PLOT, /* Plot raysums */ - TRACE_CLIPPING /* Plot clipping */ -}; +static const int TRACE_INVALID = 0xFFFF; +static const int TRACE_NONE = 0x0000; +static const int TRACE_TEXT = 0x0001; +static const int TRACE_PHM = 0x0002; +static const int TRACE_RAYS = 0x0004; +static const int TRACE_PLOT = 0x0008; +static const int TRACE_CLIPPING = 0x0010; class TraceLevel { @@ -29,7 +27,7 @@ class TraceLevel int getTraceLevel(void) const { return m_traceLevel; } - static TraceID convertTraceNameToID (const char* traceName); + static int convertTraceNameToID (const char* traceName); private: diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp index 9d3f1fc..6b826d7 100644 --- a/libctgraphics/sgp.cpp +++ b/libctgraphics/sgp.cpp @@ -7,7 +7,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: sgp.cpp,v 1.9 2000/08/02 18:06:00 kevin Exp $ +** $Id: sgp.cpp,v 1.10 2000/08/25 15:59:13 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 @@ -81,6 +81,9 @@ SGPDriver::~SGPDriver () SGP::SGP (const SGPDriver& driver) : m_driver (driver) +#if HAVE_WXWINDOWS + , m_pPen(NULL) +#endif { m_iPhysicalXSize = m_driver.getPhysicalXSize(); m_iPhysicalYSize = m_driver.getPhysicalYSize(); @@ -225,8 +228,9 @@ SGP::setColor (int icol) #if HAVE_WXWINDOWS if (m_driver.isWX()) { wxColor colour (s_aRGBColor[icol].getRed(), s_aRGBColor[icol].getGreen(), s_aRGBColor[icol].getBlue()); - wxPen pen (colour, 1, wxSOLID); - m_driver.idWX()->SetPen (pen); + delete m_pPen; + m_pPen = new wxPen (colour, 1, wxSOLID); + m_driver.idWX()->SetPen (*m_pPen); } #endif } diff --git a/libctsim/backprojectors.cpp b/libctsim/backprojectors.cpp index 7a1c55b..71aa8d4 100644 --- a/libctsim/backprojectors.cpp +++ b/libctsim/backprojectors.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: backprojectors.cpp,v 1.11 2000/07/23 01:49:03 kevin Exp $ +** $Id: backprojectors.cpp,v 1.12 2000/08/25 15:59:13 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 @@ -286,18 +286,20 @@ Backproject::ScaleImageByRotIncrement () void Backproject::errorIndexOutsideDetector (int ix, int iy, double theta, double r, double phi, double L, int iDetPos) { - printf ("r=%f, phi=%f\n", r, phi); + sys_error (ERR_WARNING, "r=%f, phi=%f", r, phi); errorIndexOutsideDetector (ix, iy, theta, L, iDetPos); } void Backproject::errorIndexOutsideDetector (int ix, int iy, double theta, double L, int iDetPos) { - printf ("ix=%d, iy=%d\n", ix, iy); - printf ("theta=%f, L=%f, detInc=%f\n", theta, L, detInc); - printf ("proj.ndet=%d, proj.detInc=%.4f, iDetCenter=%d\n", nDet, detInc, iDetCenter); - printf ("xMin=%15.8f, xMax=%15.8f, xInc=%15.8f\n", xMin, xMax, xInc); - printf ("yMin=%15.8f, yMax=%15.8f, yInc=%15.8f\n", yMin, yMax, yInc); - sys_error (ERR_WARNING, "iDetPos index outside bounds: %d [backprojector]", iDetPos); + ostringstream os; + os << "ix=" << ix << ", iy=" << iy << ", theta=" << theta << ", L=" << L << ", detinc=" << detInc << "\n"; + os << "ndet=" << nDet << ", detInc=" << detInc << ", iDetCenter=" << iDetCenter << "\n"; + os << "xMin=" << xMin << ", xMax=" << xMax << ", xInc=" << xInc << "\n"; + os << "yMin=" << yMin << ", yMax=" << yMax << ", yInc=" << yInc << "\n"; + os << "iDetPos index outside bounds: " << iDetPos << " [backprojector]";; + + sys_error (ERR_WARNING, os.str().c_str()); } @@ -543,7 +545,7 @@ BackprojectIntDiff2::BackprojectView (const double* const filteredProj, const do 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 impossible: index outside of raysum pos + if (iDetPos < 0 || iDetPos >= nDet) // check for index outside of raysum pos errorIndexOutsideDetector (ix, iy, theta, curDetPos, iDetPos); else *pImCol++ += filteredProj[iDetPos]; @@ -588,12 +590,14 @@ BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const do kint32 detPosColStart = nearest ((start_r * cos (theta - start_phi) / detInc + iDetCenter) * scale); // precalculate scaled difference for linear interpolation - double deltaFilteredProj [nDet - 1]; + double deltaFilteredProj [nDet]; if (interpType == Backprojector::INTERP_LINEAR) { for (int i = 0; i < nDet - 1; i++) deltaFilteredProj[i] = (filteredProj[i+1] - filteredProj[i]) * dInvScale; } + deltaFilteredProj[nDet - 1] = 0; // last detector + int iLastDet = nDet - 1; for (int ix = 0; ix < nx; ix++, detPosColStart += det_dx) { kint32 curDetPos = detPosColStart; ImageFileColumn pImCol = v[ix]; @@ -601,21 +605,21 @@ BackprojectIntDiff3::BackprojectView (const double* const filteredProj, const do if (interpType == Backprojector::INTERP_NEAREST) { for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { const int iDetPos = (curDetPos + halfScale) >> 16; - assert(iDetPos >= 0 && iDetPos < nDet); - *pImCol++ += filteredProj[iDetPos]; + if (iDetPos >= 0 && iDetPos <= iLastDet) + *pImCol++ += filteredProj[iDetPos]; } // end for iy } else if (interpType == Backprojector::INTERP_FREQ_PREINTERPOLATION) { for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { const int iDetPos = ((curDetPos + halfScale) >> 16) * m_interpFactor; - assert(iDetPos >= 0 && iDetPos < nDet); + if (iDetPos >= 0 && iDetPos <= iLastDet) *pImCol++ += filteredProj[iDetPos]; } // end for iy } else if (interpType == Backprojector::INTERP_LINEAR) { for (int iy = 0; iy < ny; iy++, curDetPos += det_dy) { const kint32 iDetPos = curDetPos >> scaleShift; const kint32 detRemainder = curDetPos & scaleBitmask; - assert(iDetPos >= 0 && iDetPos < nDet - 1); - *pImCol++ += filteredProj[iDetPos] + (detRemainder * deltaFilteredProj[iDetPos]); + if (iDetPos >= 0 && iDetPos <= iLastDet) + *pImCol++ += filteredProj[iDetPos] + (detRemainder * deltaFilteredProj[iDetPos]); } // end for iy } //end linear } // end for ix diff --git a/libctsim/imagefile.cpp b/libctsim/imagefile.cpp index 3f7c0be..9df4285 100644 --- a/libctsim/imagefile.cpp +++ b/libctsim/imagefile.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: imagefile.cpp,v 1.10 2000/08/22 16:49:56 kevin Exp $ +** $Id: imagefile.cpp,v 1.11 2000/08/25 15:59:13 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 @@ -66,7 +66,7 @@ ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const Ima return 0; #if HAVE_G2_H - int pens [nx * ny * scale * scale ]; + int* pPens = new int [nx * ny * scale * scale ]; double view_scale = 255 / (pmax - pmin); int id_X11 = g2_open_X11 (nx * scale, ny * scale); @@ -76,19 +76,23 @@ ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const Ima grayscale[i] = g2_ink (id_X11, cval, cval, cval); } - for (int i= 0, iy = ny - 1; iy >= 0; iy--) { - for (int ix = 0; ix < nx; ix++) { - int cval = static_cast((v[ix][iy] - pmin) * view_scale); - if (cval < 0) - cval = 0; - else if (cval > 255) - cval = 255; - pens[i++] = grayscale[cval]; + for (int iy = ny - 1; iy >= 0; iy--) { + int iRowPos = ((ny - 1 - iy) * scale) * (nx * scale); + for (int ix = 0; ix < nx; ix++) { + int cval = static_cast((v[ix][iy] - pmin) * view_scale); + if (cval < 0) + cval = 0; + else if (cval > 255) + cval = 255; + for (int sy = 0; sy < scale; sy++) + for (int sx = 0; sx < scale; sx++) + pPens[iRowPos+(sy * nx * scale)+(sx + (ix * scale))] = grayscale[cval]; } } - g2_image (id_X11, 0., 0., nx, ny, pens); + g2_image (id_X11, 0., 0., nx * scale, ny * scale, pPens); + delete pPens; return (id_X11); #endif diff --git a/libctsim/phantom.cpp b/libctsim/phantom.cpp index 09245b2..c74c37a 100644 --- a/libctsim/phantom.cpp +++ b/libctsim/phantom.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.cpp,v 1.15 2000/08/02 18:06:00 kevin Exp $ +** $Id: phantom.cpp,v 1.16 2000/08/25 15:59:13 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,26 +30,26 @@ const int Phantom::PHM_INVALID = -1; const int Phantom::PHM_HERMAN = 0; -const int Phantom::PHM_BHERMAN = 1; -const int Phantom::PHM_ROWLAND = 2; -const int Phantom::PHM_BROWLAND = 3; +const int Phantom::PHM_B_HERMAN = 1; +const int Phantom::PHM_SHEPP_LOGAN = 2; +const int Phantom::PHM_B_SHEPP_LOGAN = 3; const int Phantom::PHM_UNITPULSE = 4; const char* Phantom::s_aszPhantomName[] = { {"herman"}, - {"bherman"}, - {"rowland"}, - {"browland"}, + {"herman-b"}, + {"shepp-logan"}, + {"shepp-logan-b"}, {"unitpulse"}, }; const char* Phantom::s_aszPhantomTitle[] = { {"Herman Head"}, - {"Herman Head Bordered"}, - {"Rowland Head"}, - {"Rowland Head Bordered"}, + {"Herman Head (Bordered)"}, + {"Shepp-Logan"}, + {"Shepp-Logan (Bordered)"}, {"Unit Pulse"}, }; @@ -155,14 +155,14 @@ Phantom::createFromPhantom (const int phmid) case PHM_HERMAN: addStdHerman(); break; - case PHM_BHERMAN: + case PHM_B_HERMAN: addStdHermanBordered(); break; - case PHM_ROWLAND: - addStdRowland(); + case PHM_SHEPP_LOGAN: + addStdSheppLogan(); break; - case PHM_BROWLAND: - addStdRowlandBordered (); + case PHM_B_SHEPP_LOGAN: + addStdSheppLoganBordered(); break; case PHM_UNITPULSE: m_composition = P_UNIT_PULSE; @@ -358,7 +358,7 @@ Phantom::draw (SGP& sgp) const /* NAME - * addStdRowland Make head phantom of S.W. Rowland + * addStdSheppLogan Make head phantom of Shepp-Logan * * REFERENCES * S. W. Rowland, "Computer Implementation of Image Reconstruction @@ -367,7 +367,7 @@ Phantom::draw (SGP& sgp) const */ void -Phantom::addStdRowland () +Phantom::addStdSheppLogan () { addPElem ("ellipse", 0.0000, 0.0000, 0.6900, 0.9200, 0.0, 1.00); addPElem ("ellipse", 0.0000, -0.0184, 0.6624, 0.8740, 0.0, -0.98); @@ -383,9 +383,9 @@ Phantom::addStdRowland () } void -Phantom::addStdRowlandBordered () +Phantom::addStdSheppLoganBordered () { - addStdRowland (); + addStdSheppLogan (); addPElem ("rectangle", 0.000, 0.0000, 0.7500, 1.000, 0.0, 0.00); } @@ -421,7 +421,7 @@ void Phantom::addStdHermanBordered () { addStdHerman(); - addPElem ("rectangle", 0.000, 0.000, 8.650, 8.650, 0.00, 0.000); + addPElem ("rectangle", 0.000, 0.00, 9.000, 6.800, 0.00, 0.000); } diff --git a/libctsim/procsignal.cpp b/libctsim/procsignal.cpp index 70d759c..8156252 100644 --- a/libctsim/procsignal.cpp +++ b/libctsim/procsignal.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: procsignal.cpp,v 1.2 2000/08/22 07:02:48 kevin Exp $ +** $Id: procsignal.cpp,v 1.3 2000/08/25 15:59:13 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 @@ -77,7 +77,7 @@ const int ProcessSignal::s_iFilterGenerationCount = sizeof(s_aszFilterGeneration // CLASS IDENTIFICATION // ProcessSignal // -ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMethodName, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const char* szDomainName, const char* szFilterGenerationName, int iZeropad = 0, int iPreinterpolationFactor = 1, int iTraceLevel = TRACE_NONE) +ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMethodName, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const char* szDomainName, const char* szFilterGenerationName, int iZeropad, int iPreinterpolationFactor, int iTraceLevel) : m_adFourierCosTable(NULL), m_adFourierSinTable(NULL), m_adFilter(NULL), m_fail(false) { m_idFilterMethod = convertFilterMethodNameToID (szFilterMethodName); diff --git a/libctsim/projections.cpp b/libctsim/projections.cpp index d6b496d..df7ccd2 100644 --- a/libctsim/projections.cpp +++ b/libctsim/projections.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: projections.cpp,v 1.21 2000/08/22 07:02:48 kevin Exp $ +** $Id: projections.cpp,v 1.22 2000/08/25 15:59:13 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 @@ -81,8 +81,7 @@ Projections::initFromScanner (const Scanner& scanner) m_rotInc = scanner.rotInc(); m_detInc = scanner.detInc(); m_rotStart = 0; - m_detStart = -scanner.radius() + (scanner.detInc() / 2); - m_phmLen = scanner.phmLen(); + m_detStart = -(scanner.detLen() / 2) + (scanner.detInc() / 2); } void @@ -556,8 +555,6 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi processSignal.filterSignal (detval, filteredProj); - - #ifdef HAVE_BSPLINE_INTERP if (interp_type == I_BSPLINE) bspline (m_nDet, zoom_factor, spline_order, filteredProj, filteredProj); diff --git a/libctsim/scanner.cpp b/libctsim/scanner.cpp index 709dc0f..c4fc4d0 100644 --- a/libctsim/scanner.cpp +++ b/libctsim/scanner.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: scanner.cpp,v 1.10 2000/08/03 09:21:12 kevin Exp $ +** $Id: scanner.cpp,v 1.11 2000/08/25 15:59:13 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 @@ -82,7 +82,7 @@ DetectorArray::~DetectorArray (void) * int nSample Number of rays per detector */ -Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen) +Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, int nView, int nSample, const double rot_anglen, const double dFocalLengthRatio, const double dFieldOfViewRatio) { m_phmLen = phm.maxAxisLength(); // maximal length along an axis @@ -101,29 +101,67 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName, int nDet, m_nSample = 1; if (nDet < 1) nDet = 1; - if ((nDet % 2) == 0) - ++nDet; // ensure odd number of detectors + // if ((nDet % 2) == 0) + // ++nDet; // ensure odd number of detectors m_nDet = nDet; m_nView = nView; m_nSample = nSample; - m_detLen = SQRT2 * m_phmLen * ((m_nDet + N_EXTRA_DETECTORS) / static_cast(m_nDet)); - - m_rotLen = rot_anglen; - - m_radius = m_detLen / 2; - m_detInc = m_detLen / m_nDet; - m_rotInc = m_rotLen / m_nView; - - m_initPos.xd1 = m_detLen / 2; - m_initPos.yd1 = -m_detLen / 2; - m_initPos.xd2 = m_detLen / 2; - m_initPos.yd2 = m_detLen / 2; - m_initPos.xs1 = -m_detLen / 2; - m_initPos.ys1 = -m_detLen / 2; - m_initPos.xs2 = -m_detLen / 2; - m_initPos.ys2 = m_detLen / 2; - m_initPos.angle = 0.0; + m_dFocalLength = (m_phmLen * SQRT2 / 2) * dFocalLengthRatio; + m_dFieldOfView = m_phmLen * SQRT2 * dFieldOfViewRatio; + + if (m_idGeometry == GEOMETRY_PARALLEL) { + m_detLen = m_dFieldOfView; + m_detInc = m_detLen / m_nDet; + m_rotLen = rot_anglen; + m_rotInc = m_rotLen / m_nView; + + double dHalfDetLen = m_detLen / 2; + m_initPos.xs1 = -m_dFocalLength; + m_initPos.ys1 = -dHalfDetLen; + m_initPos.xs2 = -m_dFocalLength; + m_initPos.ys2 = dHalfDetLen; + m_initPos.xd1 = m_dFocalLength; + m_initPos.yd1 = -dHalfDetLen; + m_initPos.xd2 = m_dFocalLength; + m_initPos.yd2 = dHalfDetLen; + m_initPos.angle = 0.0; + } else if (m_idGeometry == GEOMETRY_EQUILINEAR) { + double dHalfSquare = m_phmLen / 2; + double dFocalPastPhm = m_dFocalLength - dHalfSquare; + if (dFocalPastPhm <= 0.) { + m_fail = true; + m_failMessage = "Focal Point inside of phantom"; + return; + } + double dAngle = atan( dHalfSquare / dFocalPastPhm ); + double dHalfDetLen = 2 * m_dFocalLength * tan (dAngle); + + m_detLen = dHalfDetLen * 2; + m_detInc = m_detLen / m_nDet; + m_rotLen = rot_anglen; + m_rotInc = m_rotLen / m_nView; + + m_initPos.xs1 = -m_dFocalLength; + m_initPos.ys1 = 0; + m_initPos.xs2 = -m_dFocalLength; + m_initPos.ys2 = 0; + m_initPos.xd1 = m_dFocalLength; + m_initPos.yd1 = -dHalfDetLen; + m_initPos.xd2 = m_dFocalLength; + m_initPos.yd2 = dHalfDetLen; + m_initPos.angle = 0.0; + } else if (m_idGeometry == GEOMETRY_EQUIANGULAR) { + double dHalfSquare = m_phmLen / 2; + double dFocalPastPhm = m_dFocalLength - dHalfSquare; + if (dFocalPastPhm <= 0.) { + m_fail = true; + m_failMessage = "Focal Point inside of phantom"; + return; + } + double dAngle = atan( dHalfSquare / dFocalPastPhm ); + m_detLen = dAngle * 2; + } } Scanner::~Scanner (void) @@ -169,23 +207,30 @@ Scanner::convertGeometryNameToID (const char* const geomName) /* NAME - * raysum_collect Calculate ray sums for a Phantom + * collectProjections Calculate projections for a Phantom * * SYNOPSIS - * rs = raysum_collect (det, phm, start_view, trace, unit_pulse) - * Scanner& det Scanner specifications** - * RAYSUM *rs Calculated ray sum matrix - * Phantom& phm Phantom we are taking ray sums of - * int trace Boolean flag to signal ray sum tracing + * collectProjections (proj, phm, start_view, nView, bStoreViewPos, trace) + * Projectrions& proj Projection storage + * Phantom& phm Phantom for which we collect projections + * bool bStoreViewPos TRUE then storage proj at normal view position + * int trace Trace level */ + void -Scanner::collectProjections (Projections& proj, const Phantom& phm, const int start_view = 0, const int trace = TRACE_NONE, SGP* pSGP = NULL) +Scanner::collectProjections (Projections& proj, const Phantom& phm, const int trace, SGP* pSGP) +{ + collectProjections (proj, phm, 0, proj.nView(), true, trace, pSGP); +} + +void +Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iStartView, const int iNumViews, bool bStoreAtViewPosition, const int trace, SGP* pSGP) { GRFMTX_2D rotmtx_initial, temp; GRFMTX_2D rotmtx_incr; - double start_angle = start_view * proj.rotInc(); + double start_angle = iStartView * proj.rotInc(); double xcent = phm.xmin() + (phm.xmax() - phm.xmin()) / 2; double ycent = phm.ymin() + (phm.ymax() - phm.ymin()) / 2; @@ -200,38 +245,6 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st m_trace = trace; -#ifdef HAVE_SGP - if (pSGP && m_trace >= TRACE_PHM) { - double halfPhmLen = m_phmLen / 2; - double wsize = SQRT2 * halfPhmLen; - - pSGP->setRasterOp (RO_SET); - pSGP->eraseWindow (); - pSGP->setColor (C_LTBLUE); - pSGP->setWindow (xcent - wsize, ycent - wsize, xcent + wsize, ycent + wsize); - pSGP->setColor (C_BROWN); - pSGP->drawRect (xcent - halfPhmLen, ycent - halfPhmLen, xcent + halfPhmLen, ycent + halfPhmLen); - pSGP->setColor (C_BROWN); - pSGP->moveAbs (0., 0.); - pSGP->drawCircle (wsize); - - traceShowParam ("X-Ray Simulator", "%s", RAYSUM_TRACE_ROW_TITLE, C_BLACK, " "); - traceShowParam ("---------------", "%s", RAYSUM_TRACE_ROW_TITLE2, C_BLACK, " "); - traceShowParam ("Phantom:", "%s", RAYSUM_TRACE_ROW_PHANT_ID, C_YELLOW, " Herman"); - traceShowParam ("Chomaticity :", "%s", RAYSUM_TRACE_ROW_CHROMATIC, C_LTGREEN, "Mono"); - traceShowParam ("Scatter :", "%5.1f", RAYSUM_TRACE_ROW_SCATTER, C_LTGREEN, 0.); - traceShowParam ("Photon Uncert:", "%5.1f", RAYSUM_TRACE_ROW_PHOT_STAT, C_LTGREEN, 0.); - traceShowParam ("Num Detectors:", "%5d", RAYSUM_TRACE_ROW_NDET, C_LTRED, proj.nDet()); - traceShowParam ("Num Views :", "%5d", RAYSUM_TRACE_ROW_NVIEW, C_LTRED, proj.nView()); - traceShowParam ("Samples / Ray:", "%5d", RAYSUM_TRACE_ROW_SAMPLES, C_LTRED, m_nSample); - - pSGP->setColor (C_LTGREEN); - phm.draw (*pSGP); - - pSGP->setMarker (SGP::MARK_BDIAMOND, C_LTGREEN); - } -#endif - /* Calculate initial rotation matrix */ xlat_mtx2 (rotmtx_initial, -xcent, -ycent); rot_mtx2 (temp, start_angle); @@ -253,8 +266,45 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st int iview; double viewAngle; - for (iview = 0, viewAngle = start_angle; iview < proj.nView(); iview++, viewAngle += proj.rotInc()) { - DetectorArray& detArray = proj.getDetectorArray( iview ); + for (iview = 0, viewAngle = start_angle; iview < iNumViews; iview++, viewAngle += proj.rotInc()) { + int iStoragePosition = iview; + if (bStoreAtViewPosition) + iStoragePosition += iStartView; + + DetectorArray& detArray = proj.getDetectorArray( iStoragePosition ); + +#ifdef HAVE_SGP + if (pSGP && m_trace >= TRACE_PHM) { + pSGP->eraseWindow(); + double dWindowSize = max(m_detLen, m_dFocalLength * 2) * SQRT2; + double dHalfWindowSize = dWindowSize / 2; + double dHalfPhmLen = m_phmLen / 2; + + pSGP->setRasterOp (RO_SET); + pSGP->eraseWindow (); + pSGP->setWindow (xcent - dHalfWindowSize, ycent - dHalfWindowSize, xcent + dHalfWindowSize, ycent + dHalfWindowSize); + pSGP->setColor (C_BROWN); + pSGP->moveAbs (0., 0.); + pSGP->drawRect (xcent - dHalfPhmLen, ycent - dHalfPhmLen, xcent + dHalfPhmLen, ycent + dHalfPhmLen); + +#if 0 + traceShowParam (pSGP, "X-Ray Simulator", "%s", RAYSUM_TRACE_ROW_TITLE, C_BLACK, " "); + traceShowParam (pSGP, "---------------", "%s", RAYSUM_TRACE_ROW_TITLE2, C_BLACK, " "); + traceShowParam (pSGP, "Phantom:", "%s", RAYSUM_TRACE_ROW_PHANT_ID, C_YELLOW, " Herman"); + traceShowParam (pSGP, "Chomaticity :", "%s", RAYSUM_TRACE_ROW_CHROMATIC, C_LTGREEN, "Mono"); + traceShowParam (pSGP, "Scatter :", "%5.1f", RAYSUM_TRACE_ROW_SCATTER, C_LTGREEN, 0.); + traceShowParam (pSGP, "Photon Uncert:", "%5.1f", RAYSUM_TRACE_ROW_PHOT_STAT, C_LTGREEN, 0.); + traceShowParam (pSGP, "Num Detectors:", "%5d", RAYSUM_TRACE_ROW_NDET, C_LTRED, proj.nDet()); + traceShowParam (pSGP, "Num Views :", "%5d", RAYSUM_TRACE_ROW_NVIEW, C_LTRED, proj.nViews()); + traceShowParam (pSGP, "Samples / Ray:", "%5d", RAYSUM_TRACE_ROW_SAMPLES, C_LTRED, m_nSample); +#endif + + pSGP->setColor (C_RED); + phm.draw (*pSGP); + + pSGP->setMarker (SGP::MARK_BDIAMOND, C_LTGREEN); + } +#endif #ifdef HAVE_SGP if (pSGP && m_trace >= TRACE_PHM) { @@ -264,9 +314,10 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st pSGP->lineAbs (xd2, yd2); pSGP->moveAbs (xs1, ys1); pSGP->lineAbs (xs2, ys2); + pSGP->setRasterOp (RO_SET); } - if (m_trace) - traceShowParam ("Current View :", "%5d", RAYSUM_TRACE_ROW_CURR_VIEW, C_LTMAGENTA, iview); + if (m_trace >= TRACE_TEXT) + traceShowParam (pSGP, "Current View :", "%5d", RAYSUM_TRACE_ROW_CURR_VIEW, C_LTMAGENTA, iview); #endif projectSingleView (phm, detArray, xd1, yd1, xd2, yd2, xs1, ys1, xs2, ys2, pSGP); @@ -276,10 +327,12 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int st if (pSGP && m_trace >= TRACE_PHM) { // rs_plot (detArray, xd1, yd1, xcent, ycent, theta); pSGP->setColor (C_RED); + pSGP->setRasterOp (RO_XOR); pSGP->moveAbs (xd1, yd1); pSGP->lineAbs (xd2, yd2); pSGP->moveAbs (xs1, ys1); pSGP->lineAbs (xs2, ys2); + pSGP->setRasterOp (RO_SET); } #endif xform_mtx2 (rotmtx_incr, xd1, yd1); // rotate detector endpoints @@ -350,20 +403,25 @@ Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const d #ifdef HAVE_SGP if (pSGP && m_trace >= TRACE_RAYS) { pSGP->setColor (C_LTBLUE); + pSGP->setRasterOp (RO_XOR); pSGP->moveAbs (xs, ys); pSGP->lineAbs (xd, yd); + pSGP->setRasterOp (RO_SET); } #endif sum += projectSingleLine (phm, xd, yd, xs, ys, pSGP); #ifdef HAVE_SGP - if (m_trace >= TRACE_RAYS) - traceShowParam ("Attenuation :", "%5.2f", RAYSUM_TRACE_ROW_ATTEN, C_LTMAGENTA, "sum"); + if (m_trace >= TRACE_RAYS) { + traceShowParam (pSGP, "Attenuation :", "%5.2f", RAYSUM_TRACE_ROW_ATTEN, C_LTMAGENTA, sum); + } if (pSGP && m_trace >= TRACE_RAYS) { pSGP->setColor (C_LTBLUE); + pSGP->setRasterOp (RO_XOR); pSGP->moveAbs (xs, ys); pSGP->lineAbs (xd, yd); + pSGP->setRasterOp (RO_SET); } #endif xd += ddx2; @@ -381,20 +439,30 @@ Scanner::projectSingleView (const Phantom& phm, DetectorArray& detArray, const d void -Scanner::traceShowParam (const char *label, const char *fmt, int row, int color, ...) +Scanner::traceShowParam (SGP* pSGP, const char *label, const char *fmt, int row, int color, ...) { - char s[80]; + char s[256]; va_list arg; va_start(arg, color); - // cio_set_cpos (raysum_trace_menu_column, row); snprintf (s, sizeof(s), label, "%s"); - // cio_set_text_clr (color - 8, 0); - cio_put_str (s); + string strOut(s); vsnprintf (s, sizeof(s), fmt, arg); + strOut += s; + + // cio_set_cpos (raysum_trace_menu_column, row); + // cio_set_text_clr (color - 8, 0); // cio_set_text_clr (color, 0); - cio_put_str (s); - cout << "\n"; + + if (pSGP) { + pSGP->moveAbs (0., row * 0.04); + pSGP->setTextColor (color, -1); + pSGP->drawText (strOut); + } else { + cio_put_str (strOut.c_str()); + cio_put_str ("\n"); + } + va_end(arg); } @@ -442,11 +510,13 @@ Scanner::projectLineAgainstPElem (const PhantomElement& pelem, double x1, double #ifdef HAVE_SGP if (pSGP && m_trace == TRACE_CLIPPING) { + pSGP->setRasterOp (RO_XOR); pSGP->moveAbs (x1, y1); pSGP->lineAbs (x2, y2); cio_tone (8000., 0.05); pSGP->moveAbs (x1, y1); pSGP->lineAbs (x2, y2); + pSGP->setRasterOp (RO_SET); } #endif diff --git a/libctsim/trace.cpp b/libctsim/trace.cpp index 3bb8ce8..dced2c6 100644 --- a/libctsim/trace.cpp +++ b/libctsim/trace.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: trace.cpp,v 1.1 2000/07/20 11:17:31 kevin Exp $ +** $Id: trace.cpp,v 1.2 2000/08/25 15:59:13 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 @@ -34,10 +34,10 @@ const char TraceLevel::TRACE_PLOT_STR[]= "plot"; const char TraceLevel::TRACE_CLIPPING_STR[]= "clipping"; -TraceID +int TraceLevel::convertTraceNameToID (const char *traceString) { - TraceID traceID = TRACE_INVALID; + int traceID = TRACE_INVALID; if (strcasecmp (traceString, TRACE_NONE_STR) == 0) traceID = TRACE_NONE; diff --git a/libctsupport/syserror.cpp b/libctsupport/syserror.cpp index 28ccba4..e59449f 100644 --- a/libctsupport/syserror.cpp +++ b/libctsupport/syserror.cpp @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: syserror.cpp,v 1.3 2000/06/19 19:04:05 kevin Exp $ +** $Id: syserror.cpp,v 1.4 2000/08/25 15:59:13 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 @@ -58,7 +58,7 @@ const static int MAX_ERROR_COUNT = 20; void sys_verror (int severity, const char *msg, va_list arg) { if (severity < errorlevel) - return; /* ignore error if less than max level */ + return; // ignore error if less than max level nErrorCount++; if (severity != ERR_FATAL) { diff --git a/src/ctsim.h b/src/ctsim.h index c013a34..6185d86 100644 --- a/src/ctsim.h +++ b/src/ctsim.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ctsim.h,v 1.4 2000/07/23 01:49:03 kevin Exp $ +** $Id: ctsim.h,v 1.5 2000/08/25 15:59:13 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 @@ -98,8 +98,8 @@ enum { PJMENU_FILE_PROPERTIES, PHMMENU_FILE_PROPERTIES, PJMENU_PROCESS_RECONSTRUCT, - IFMENU_VIEW_WINDOW_AUTO, - IFMENU_VIEW_WINDOW_MINMAX, + IFMENU_VIEW_SCALE_AUTO, + IFMENU_VIEW_SCALE_MINMAX, PHMMENU_PROCESS_RASTERIZE, PHMMENU_PROCESS_PROJECTIONS, }; diff --git a/src/dialogs.cpp b/src/dialogs.cpp index 4b2738f..ef5ece2 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.cpp,v 1.8 2000/08/22 07:02:48 kevin Exp $ +** $Id: dialogs.cpp,v 1.9 2000/08/25 15:59:13 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 @@ -280,11 +280,18 @@ DialogGetRasterParameters::getNSamples (void) ///////////////////////////////////////////////////////////////////// -DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL) - : wxDialog (pParent, -1, "Set Projection Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) +DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL) + : wxDialog (pParent, -1, "Set Projection Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) { wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); + m_dDefaultRotAngle = dDefaultRotAngle; + m_dDefaultFocalLength = dDefaultFocalLength; + m_dDefaultFieldOfView = dDefaultFieldOfView; + m_iDefaultNSamples = iDefaultNSamples; + m_iDefaultNView = iDefaultNView; + m_iDefaultNDet = iDefaultNDet; + pTopSizer->Add (new wxStaticText (this, -1, "Set Projection Parameters"), 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 5); pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); @@ -305,6 +312,12 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, ostringstream osRotAngle; osRotAngle << dDefaultRotAngle; m_pTextCtrlRotAngle = new wxTextCtrl (this, -1, osRotAngle.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + ostringstream osFocalLength; + osFocalLength << dDefaultFocalLength; + m_pTextCtrlFocalLength = new wxTextCtrl (this, -1, osFocalLength.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + ostringstream osFieldOfView; + osFieldOfView << dDefaultFieldOfView; + m_pTextCtrlFieldOfView = new wxTextCtrl (this, -1, osFieldOfView.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); wxGridSizer *pGridSizer = new wxGridSizer (2, 4, 5); pGridSizer->Add (new wxStaticText (this, -1, "Detectors"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); @@ -315,6 +328,10 @@ DialogGetProjectionParameters::DialogGetProjectionParameters (wxFrame* pParent, pGridSizer->Add (m_pTextCtrlNSamples, 0, wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Rotation Angle (PI units)"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlRotAngle, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (new wxStaticText (this, -1, "Focal Length Ratio (phantom radius units)"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlFocalLength, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (new wxStaticText (this, -1, "Field of View (phantom diameter units)"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlFieldOfView, 0, wxALIGN_CENTER_VERTICAL); pTopSizer->Add (pGridSizer, 1, wxALL, 10); pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); @@ -383,6 +400,28 @@ DialogGetProjectionParameters::getRotAngle (void) return (m_dDefaultRotAngle); } +double +DialogGetProjectionParameters::getFocalLengthRatio (void) +{ + wxString strCtrl = m_pTextCtrlFocalLength->GetValue(); + double dValue; + if (strCtrl.ToDouble (&dValue)) + return (dValue); + else + return (m_dDefaultFocalLength); +} + +double +DialogGetProjectionParameters::getFieldOfViewRatio (void) +{ + wxString strCtrl = m_pTextCtrlFieldOfView->GetValue(); + double dValue; + if (strCtrl.ToDouble (&dValue)) + return (dValue); + else + return (m_dDefaultFieldOfView); +} + const char* DialogGetProjectionParameters::getGeometry (void) { @@ -561,3 +600,69 @@ DialogGetReconstructionParameters::getFilterGenerationName (void) { return m_pListBoxFilterGeneration->getSelectionStringValue(); } + + +DialogAutoScaleParameters::DialogAutoScaleParameters (wxFrame *pParent, const ImageFile& rIF) + : wxDialog (pParent, -1, "Auto Scale Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION), m_rImageFile(rIF) +{ + wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); + + pTopSizer->Add (new wxStaticText (this, -1, "Auto Scale Parameters"), 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 5); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + + wxString asTitle[3]; + asTitle[0] = "Median"; + asTitle[1] = "Mode"; + asTitle[2] = "Mean"; + + m_pListBoxCenter = new wxListBox (this, -1, wxDefaultPosition, wxDefaultSize, 3, asTitle, wxLB_SINGLE | wxLB_NEEDED_SB); + m_pListBoxCenter->SetSelection (0); + pTopSizer->Add (m_pListBoxCenter, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + + wxGridSizer *pGridSizer = new wxGridSizer (2, 2, 5); + pGridSizer->Add (new wxStaticText (this, -1, "Standard Deviation Factor"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + m_pTextCtrlStdDevFactor = new wxTextCtrl (this, -1, "1.0", wxDefaultPosition, wxSize(100, 25), 0); + pGridSizer->Add (m_pTextCtrlStdDevFactor, 0, wxALIGN_CENTER_VERTICAL); + pTopSizer->Add (pGridSizer, 1, wxALL, 10); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + + wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL); + wxButton* pButtonOk = new wxButton (this, wxID_OK, "Okay"); + wxButton* pButtonCancel = new wxButton (this, wxID_CANCEL, "Cancel"); + pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10); + pButtonSizer->Add (pButtonCancel, 0, wxEXPAND | wxALL, 10); + + pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER); + + SetAutoLayout (true); + SetSizer (pTopSizer); + pTopSizer->Fit (this); + pTopSizer->SetSizeHints (this); +} + +void +DialogAutoScaleParameters::getMinMax (double* pMin, double* pMax) +{ + int iCenter = m_pListBoxCenter->GetSelection(); + double min, max, mean, mode, median, stddev; + m_rImageFile.statistics (min, max, mean, mode, median, stddev); + double dCenter = median; + if (iCenter == 1) + dCenter = mode; + else if (iCenter == 2) + dCenter = mean; + + wxString sStddevFactor = m_pTextCtrlStdDevFactor->GetValue(); + double dValue; + if (! sStddevFactor.ToDouble (&dValue)) { + *theApp->getLog() << "Error: Non-numeric Standard Deviation Factor of " << sStddevFactor << "\n"; + *pMin = min; + *pMax = max; + } + double dHalfWidth = dValue * stddev / 2; + *pMin = dCenter - dHalfWidth; + *pMax = dCenter + dHalfWidth; + *theApp->getLog() << "Setting minimum to " << *pMin << " and maximum to " << *pMax << "\n"; +} diff --git a/src/dialogs.h b/src/dialogs.h index e4f890c..7298348 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.h,v 1.9 2000/08/22 07:02:48 kevin Exp $ +** $Id: dialogs.h,v 1.10 2000/08/25 15:59:13 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 @@ -109,13 +109,15 @@ class DialogGetRasterParameters : public wxDialog class DialogGetProjectionParameters : public wxDialog { public: - DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL); + DialogGetProjectionParameters (wxFrame* pParent, int iDefaultNDet = 0, int iDefaultNView = 0, int iDefaultNSamples = 1, double dDefaultRotAngle = 1., double dDefaultFocalLength = 1, double dDefaultFieldOfView = 1., int iDefaultGeometry = Scanner::GEOMETRY_PARALLEL); ~DialogGetProjectionParameters (void); unsigned int getNDet (void); unsigned int getNView (void); unsigned int getNSamples (void); double getRotAngle (void); + double getFieldOfViewRatio (void); + double getFocalLengthRatio (void); const char* getGeometry(void); private: @@ -123,6 +125,8 @@ class DialogGetProjectionParameters : public wxDialog wxTextCtrl* m_pTextCtrlNView; wxTextCtrl* m_pTextCtrlNSamples; wxTextCtrl* m_pTextCtrlRotAngle; + wxTextCtrl* m_pTextCtrlFocalLength; + wxTextCtrl* m_pTextCtrlFieldOfView; StringValueAndTitleListBox* m_pListBoxGeometry; @@ -130,6 +134,8 @@ class DialogGetProjectionParameters : public wxDialog int m_iDefaultNView; int m_iDefaultNSamples; double m_dDefaultRotAngle; + double m_dDefaultFocalLength; + double m_dDefaultFieldOfView; }; @@ -171,5 +177,20 @@ class DialogGetReconstructionParameters : public wxDialog int m_iDefaultInterpParam; }; +class DialogAutoScaleParameters : public wxDialog +{ + public: + DialogAutoScaleParameters (wxFrame* pParent, const ImageFile& rImageFile); + virtual ~DialogAutoScaleParameters() {} + + void getMinMax (double* pMin, double* pMax); + + private: + const ImageFile& m_rImageFile; + + wxTextCtrl* m_pTextCtrlStdDevFactor; + wxListBox* m_pListBoxCenter; +}; + #endif diff --git a/src/views.cpp b/src/views.cpp index 4cb6f69..1cd730e 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.cpp,v 1.15 2000/08/22 16:49:56 kevin Exp $ +** $Id: views.cpp,v 1.16 2000/08/25 15:59:13 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 @@ -108,8 +108,8 @@ IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView) BEGIN_EVENT_TABLE(ImageFileView, wxView) EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties) - EVT_MENU(IFMENU_VIEW_WINDOW_MINMAX, ImageFileView::OnWindowMinMax) - EVT_MENU(IFMENU_VIEW_WINDOW_AUTO, ImageFileView::OnWindowAuto) + EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax) + EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto) END_EVENT_TABLE() ImageFileView::ImageFileView(void) @@ -148,13 +148,24 @@ ImageFileView::OnProperties (wxCommandEvent& event) } void -ImageFileView::OnWindowAuto (wxCommandEvent& event) +ImageFileView::OnScaleAuto (wxCommandEvent& event) { - *theApp->getLog() << "ImageFile: Window Auto\n"; + const ImageFile& rIF = GetDocument()->getImageFile(); + DialogAutoScaleParameters dialogAutoScale (m_frame, rIF); + int iRetVal = dialogAutoScale.ShowModal(); + if (iRetVal == wxID_OK) { + m_bMinSpecified = true; + m_bMaxSpecified = true; + double dMin, dMax; + dialogAutoScale.getMinMax (&dMin, &dMax); + m_dMinPixel = dMin; + m_dMaxPixel = dMax; + OnUpdate (this, NULL); + } } void -ImageFileView::OnWindowMinMax (wxCommandEvent& event) +ImageFileView::OnScaleMinMax (wxCommandEvent& event) { const ImageFile& rIF = GetDocument()->getImageFile(); double min, max; @@ -216,8 +227,8 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(wxID_PREVIEW, "Print Pre&view"); wxMenu *view_menu = new wxMenu; - view_menu->Append(IFMENU_VIEW_WINDOW_MINMAX, "&Set Window Min/Max"); - view_menu->Append(IFMENU_VIEW_WINDOW_AUTO, "&Auto Window..."); + view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale &Set..."); + view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto..."); wxMenu *help_menu = new wxMenu; help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); @@ -391,19 +402,26 @@ PhantomView::OnProperties (wxCommandEvent& event) void PhantomView::OnProjections (wxCommandEvent& event) { - DialogGetProjectionParameters dialogProjection (m_frame, 367, 320, 1, 1., Scanner::GEOMETRY_PARALLEL); + DialogGetProjectionParameters dialogProjection (m_frame, 367, 320, 1, 1., 1., 1., Scanner::GEOMETRY_PARALLEL); int retVal = dialogProjection.ShowModal(); if (retVal == wxID_OK) { int nDet = dialogProjection.getNDet(); int nView = dialogProjection.getNView(); int nSamples = dialogProjection.getNSamples(); double dRotAngle = dialogProjection.getRotAngle(); + double dFocalLengthRatio = dialogProjection.getFocalLengthRatio(); + double dFieldOfViewRatio = dialogProjection.getFieldOfViewRatio(); + wxString sGeometry = dialogProjection.getGeometry(); if (nDet > 0 && nView > 0 && sGeometry != "") { const Phantom& rPhantom = GetDocument()->getPhantom(); ProjectionFileDocument* pProjectionDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT)); Projections& rProj = pProjectionDoc->getProjections(); - Scanner theScanner (rPhantom, sGeometry.c_str(), nDet, nView, nSamples, dRotAngle); + Scanner theScanner (rPhantom, sGeometry.c_str(), nDet, nView, nSamples, dRotAngle, dFocalLengthRatio, dFieldOfViewRatio); + if (theScanner.fail()) { + *theApp->getLog() << "Failed making scanner: " << theScanner.failMessage().c_str() << "\n"; + return; + } rProj.initFromScanner (theScanner); #if 1 @@ -414,7 +432,9 @@ PhantomView::OnProjections (wxCommandEvent& event) frame.GetClientSize(&x, &y); SGPDriver driver (dynamic_cast(&dc), x, y); SGP sgp (driver); - theScanner.collectProjections (rProj, rPhantom, 0, TRACE_PHM, &sgp); + for (int iView = 0; iView < rProj.nView(); iView++) { + theScanner.collectProjections (rProj, rPhantom, iView, 1, true, TRACE_RAYS, &sgp); + } #else theScanner.collectProjections (rProj, rPhantom); #endif @@ -422,7 +442,7 @@ PhantomView::OnProjections (wxCommandEvent& event) pProjectionDoc->Modify(true); pProjectionDoc->UpdateAllViews(this); ostringstream os; - os << "Projections for " << rPhantom.name() << ": nDet=" << nDet << ", nView=" << nView << ", nSamples=" << nSamples << ", RotAngle=" << dRotAngle << ", Geometry=" << sGeometry.c_str() << "\n"; + os << "Projections for " << rPhantom.name() << ": nDet=" << nDet << ", nView=" << nView << ", nSamples=" << nSamples << ", RotAngle=" << dRotAngle << ", FocalLengthRatio=" << dFocalLengthRatio << ", FieldOfViewRatio=" << dFieldOfViewRatio << ", Geometry=" << sGeometry.c_str() << "\n"; *theApp->getLog() << os.str().c_str(); } } diff --git a/src/views.h b/src/views.h index 3c29c77..a11cfaf 100644 --- a/src/views.h +++ b/src/views.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.h,v 1.6 2000/07/28 08:28:08 kevin Exp $ +** $Id: views.h,v 1.7 2000/08/25 15:59:13 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 @@ -64,8 +64,8 @@ public: void OnUpdate(wxView *sender, wxObject *hint = NULL); bool OnClose (bool deleteWindow = true); void OnProperties (wxCommandEvent& event); - void OnWindowAuto (wxCommandEvent& event); - void OnWindowMinMax (wxCommandEvent& event); + void OnScaleAuto (wxCommandEvent& event); + void OnScaleMinMax (wxCommandEvent& event); ImageFileDocument* GetDocument(void) { return dynamic_cast(wxView::GetDocument()); } diff --git a/tools/if2img.cpp b/tools/if2img.cpp index d9e7004..d17409e 100644 --- a/tools/if2img.cpp +++ b/tools/if2img.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: if2img.cpp,v 1.5 2000/08/22 17:03:54 kevin Exp $ +** $Id: if2img.cpp,v 1.6 2000/08/25 15:59:13 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 @@ -48,7 +48,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: if2img.cpp,v 1.5 2000/08/22 17:03:54 kevin Exp $"; +static const char* g_szIdStr = "$Id: if2img.cpp,v 1.6 2000/08/25 15:59:13 kevin Exp $"; enum { O_AUTO_FULL, O_AUTO_STD0_1, O_AUTO_STD0_5, O_AUTO_STD1, O_AUTO_STD2, O_AUTO_STD3 }; static const char O_AUTO_FULL_STR[]="full"; @@ -259,12 +259,16 @@ if2img_main (int argc, char *const argv[]) } } +#if HAVE_SGP + if (optind + 1 == argc) + opt_format = O_FORMAT_DISP; // display image if no options +#endif + if ((opt_format == O_FORMAT_DISP && optind + 1 != argc) - || (opt_format != O_FORMAT_DISP && optind + 2 != argc)) - { - if2img_usage(argv[0]); - return (1); - } + || (opt_format != O_FORMAT_DISP && optind + 2 != argc)) { + if2img_usage(argv[0]); + return (1); + } in_file = argv[optind]; diff --git a/tools/phm2if.cpp b/tools/phm2if.cpp index b4338c9..9ff3b9a 100644 --- a/tools/phm2if.cpp +++ b/tools/phm2if.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2if.cpp,v 1.9 2000/08/03 09:57:29 kevin Exp $ +** $Id: phm2if.cpp,v 1.10 2000/08/25 15:59:13 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 @@ -50,7 +50,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.9 2000/08/03 09:57:29 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $"; void phm2if_usage (const char *program) @@ -63,9 +63,9 @@ phm2if_usage (const char *program) cout << " ny Number of pixels Y-axis" << endl; cout << " --phantom Phantom to use for projection" << endl; cout << " herman Herman head phantom" << endl; - cout << " bherman Bordered Herman head phantom" << endl; - cout << " rowland Rowland head phantom" << endl; - cout << " browland Bordered Rowland head phantom" << endl; + cout << " herman-b Herman head phantom (Bordered)" << endl; + cout << " shepp-logan Shepp-Logan head phantom" << endl; + cout << " shepp-logan-b Shepp-Logan head phantom (Bordered)" << endl; cout << " unitpulse Unit pulse phantom" << endl; cout << " --phmfile Generate Phantom from phantom file" << endl; cout << " --filter Generate Phantom from a filter function" << endl; diff --git a/tools/phm2pj.cpp b/tools/phm2pj.cpp index 82cad2f..2bc4d98 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.9 2000/08/03 09:57:29 kevin Exp $ +** $Id: phm2pj.cpp,v 1.10 2000/08/25 15:59:13 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 @@ -29,7 +29,7 @@ #include "timer.h" -enum { O_PHANTOM, O_DESC, O_NRAY, O_ROTANGLE, O_PHMFILE, +enum { O_PHANTOM, O_DESC, O_NRAY, O_ROTANGLE, O_PHMFILE, O_GEOMETRY, O_FOCAL_LENGTH, O_FIELD_OF_VIEW, O_TRACE, O_VERBOSE, O_HELP, O_DEBUG, O_VERSION }; static struct option phm2pj_options[] = @@ -39,6 +39,9 @@ static struct option phm2pj_options[] = {"desc", 1, 0, O_DESC}, {"nray", 1, 0, O_NRAY}, {"rotangle", 1, 0, O_ROTANGLE}, + {"geometry", 1, 0, O_GEOMETRY}, + {"focal-length", 1, 0, O_FOCAL_LENGTH}, + {"field-of-view", 1, 0, O_FIELD_OF_VIEW}, {"trace", 1, 0, O_TRACE}, {"verbose", 0, 0, O_VERBOSE}, {"help", 0, 0, O_HELP}, @@ -47,39 +50,43 @@ static struct option phm2pj_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.9 2000/08/03 09:57:29 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.10 2000/08/25 15:59:13 kevin Exp $"; void phm2pj_usage (const char *program) { - cout << "usage: " << fileBasename(program) << " outfile ndet nview [--phantom phantom-name] [--phmfile filename] [OPTIONS]" << endl; - cout << "Calculate (projections) through phantom object, either a predefined --phantom or a --phmfile" << endl; - cout << "" << endl; - cout << " outfile Name of output file for raysums" << endl; - cout << " ndet Number of detectors" << endl; - cout << " nview Number of rotated views" << endl; - cout << " --phantom Phantom to use for projection" << endl; - cout << " herman Herman head phantom" << endl; - cout << " bherman Bordered herman head phantom" << endl; - cout << " rowland Rowland head phantom" << endl; - cout << " browland Bordered Rowland head phantom" << endl; - cout << " unitpulse Unit pulse phantom" << endl; - cout << " --phmfile Get Phantom from phantom file" << endl; - cout << " --desc Description of raysum" << endl; - cout << " --nray Number of rays per detector (default = 1)" << endl; - cout << " --rotangle Degrees to rotate view through, multiple of PI (default = 1)" << endl; - cout << " --trace Trace level to use" << endl; - cout << " none No tracing (default)" << endl; - cout << " text Trace text level" << endl; - cout << " phm Trace phantom image" << endl; - cout << " rays Trace rays" << endl; - cout << " plot Trace plot" << endl; - cout << " clipping Trace clipping" << endl; - cout << " --verbose Verbose mode" << endl; - cout << " --debug Debug mode" << endl; - cout << " --version Print version" << endl; - cout << " --help Print this help message" << endl; + cout << "usage: " << fileBasename(program) << " outfile ndet nview [--phantom phantom-name] [--phmfile filename] [OPTIONS]\n"; + cout << "Calculate (projections) through phantom object, either a predefined --phantom or a --phmfile\n\n"; + cout << " outfile Name of output file for raysums\n"; + cout << " ndet Number of detectors\n"; + cout << " nview Number of rotated views\n"; + cout << " --phantom Phantom to use for projection\n"; + cout << " herman Herman head phantom\n"; + cout << " herman-b Herman head phantom (Bordered)\n"; + cout << " shepp-logan Shepp-Logan head phantom\n"; + cout << " shepp-logan-b Shepp-Logan head phantom (Bordered)\n"; + cout << " unitpulse Unit pulse phantom\n"; + cout << " --phmfile Get Phantom from phantom file\n"; + cout << " --desc Description of raysum\n"; + cout << " --nray Number of rays per detector (default = 1)\n"; + cout << " --rotangle Degrees to rotate view through (multiple of PI)\n"; + cout << " (default = 1)\n"; + cout << " --focal-length Focal length ratio (ratio to radius of phantom)\n"; + cout << " (default = 1)\n"; + cout << " --field-of-view Field of view (ratio to diameter of phantom square)\n"; + cout << " (default = 1)\n"; + cout << " --trace Trace level to use\n"; + cout << " none No tracing (default)\n"; + cout << " text Trace text level\n"; + cout << " phm Trace phantom image\n"; + cout << " rays Trace rays\n"; + cout << " plot Trace plot\n"; + cout << " clipping Trace clipping\n"; + cout << " --verbose Verbose mode\n"; + cout << " --debug Debug mode\n"; + cout << " --version Print version\n"; + cout << " --help Print this help message\n"; } #ifdef HAVE_MPI @@ -97,6 +104,8 @@ phm2pj_main (int argc, char* argv[]) int opt_ndet; int opt_nview; int opt_nray = 1; + double dOptFocalLength = 1.; + double dOptFieldOfView = 1.; int opt_trace = 0; string optPhmName (Phantom::convertPhantomIDToName(Phantom::PHM_HERMAN)); int opt_verbose = 0; @@ -152,6 +161,27 @@ phm2pj_main (int argc, char* argv[]) return (1); } break; + case O_GEOMETRY: + optGeometryName = optarg; + break; + case O_FOCAL_LENGTH: + dOptFocalLength = strtod(optarg, &endptr); + endstr = optarg + strlen(optarg); + if (endptr != endstr) { + cerr << "Error setting --focal-length to " << optarg << endl; + phm2pj_usage(argv[0]); + return (1); + } + break; + case O_FIELD_OF_VIEW: + dOptFieldOfView = strtod(optarg, &endptr); + endstr = optarg + strlen(optarg); + if (endptr != endstr) { + cerr << "Error setting --field-of-view to " << optarg << endl; + phm2pj_usage(argv[0]); + return (1); + } + break; case O_NRAY: opt_nray = strtol(optarg, &endptr, 10); endstr = optarg + strlen(optarg); @@ -165,7 +195,7 @@ phm2pj_main (int argc, char* argv[]) #ifdef VERSION cout << "Version: " << VERSION << endl << g_szIdStr << endl; #else - cout << "Unknown version number" << endl; + cout << "Unknown version number\n"; #endif return (0); case O_HELP: @@ -179,7 +209,7 @@ phm2pj_main (int argc, char* argv[]) } if (optPhmName == "" && optPhmFileName == "") { - cerr << "No phantom defined" << endl << endl; + cerr << "No phantom defined\n" << endl; phm2pj_usage(argv[0]); return (1); } @@ -227,7 +257,7 @@ phm2pj_main (int argc, char* argv[]) if (optPhmFileName != "") { #ifdef HAVE_MPI - cerr << "Can not read phantom from file in MPI mode" << endl; + cerr << "Can not read phantom from file in MPI mode\n"; return (1); #endif phm.createFromFile (optPhmFileName.c_str()); @@ -254,7 +284,7 @@ phm2pj_main (int argc, char* argv[]) #endif opt_rotangle *= PI; - Scanner scanner (phm, optGeometryName.c_str(), opt_ndet, opt_nview, opt_nray, opt_rotangle); + Scanner scanner (phm, optGeometryName.c_str(), opt_ndet, opt_nview, opt_nray, opt_rotangle, dOptFocalLength, dOptFieldOfView); if (scanner.fail()) { cout << "Scanner Creation Error: " << scanner.failMessage() << endl; return (1); @@ -273,10 +303,10 @@ phm2pj_main (int argc, char* argv[]) pjLocal.setNView (mpiWorld.getMyLocalWorkUnits()); if (opt_debug) - cout << "pjLocal->nview = " << pjLocal.nView() << " (process " << mpiWorld.getRank() << ")" << endl;; + cout << "pjLocal->nview = " << pjLocal.nView() << " (process " << mpiWorld.getRank() << ")\n";; TimerCollectiveMPI timerProject (mpiWorld.getComm()); - scanner.collectProjections (pjLocal, phm, mpiWorld.getMyStartWorkUnit(), opt_trace); + scanner.collectProjections (pjLocal, phm, mpiWorld.getMyStartWorkUnit(), mpiWorld.getMyLocalWorkUnits(), false, opt_trace); if (opt_verbose) timerProject.timerEndAndReport ("Time to collect projections"); @@ -294,7 +324,7 @@ phm2pj_main (int argc, char* argv[]) pSGPDriver = new SGPDriver ("phm2pj", 600, 600); pSGP = new SGP (*pSGPDriver); } - scanner.collectProjections (pjGlobal, phm, 0, opt_trace, pSGP); + scanner.collectProjections (pjGlobal, phm, opt_trace, pSGP); if (opt_trace >= TRACE_PHM) { cout << "Press enter to continue\n"; cio_kb_getc(); @@ -303,7 +333,7 @@ phm2pj_main (int argc, char* argv[]) } #else - scanner.collectProjections (pjGlobal, phm, 0, opt_trace); + scanner.collectProjections (pjGlobal, phm, opt_trace); #endif #endif @@ -321,7 +351,7 @@ phm2pj_main (int argc, char* argv[]) pjGlobal.printScanInfo(); cout << endl; cout << " Remark: " << pjGlobal.remark() << endl; - cout << "Run time: " << pjGlobal.calcTime() << " seconds" << endl; + cout << "Run time: " << pjGlobal.calcTime() << " seconds\n"; } } @@ -384,7 +414,7 @@ main (int argc, char* argv[]) } catch (exception e) { cerr << "Exception: " << e.what() << endl; } catch (...) { - cerr << "Unknown exception" << endl; + cerr << "Unknown exception\n"; } return (retval); diff --git a/tools/pjrec.cpp b/tools/pjrec.cpp index 10adbff..19b9b86 100644 --- a/tools/pjrec.cpp +++ b/tools/pjrec.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: pjrec.cpp,v 1.13 2000/08/22 07:02:48 kevin Exp $ +** $Id: pjrec.cpp,v 1.14 2000/08/25 15:59:13 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,7 +49,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: pjrec.cpp,v 1.13 2000/08/22 07:02:48 kevin Exp $"; +static const char* g_szIdStr = "$Id: pjrec.cpp,v 1.14 2000/08/25 15:59:13 kevin Exp $"; void pjrec_usage (const char *program) @@ -92,7 +92,7 @@ pjrec_usage (const char *program) cout << " --zeropad n Set zeropad level (default = 0)\n"; cout << " set n to number of powers to two to pad\n"; cout << " --filter-generation Filter Generation mode\n"; - cout << " direct Use direct filter in spatial or frequency domain\n"; + cout << " direct Use direct filter in spatial or frequency domain (default)\n"; cout << " inverse_fourier Use inverse fourier transform of inverse filter\n"; cout << " --backproj Backprojection Method" << endl; cout << " trig Trigometric functions at every point" << endl; @@ -132,12 +132,12 @@ pjrec_main (int argc, char * argv[]) string sRemark; bool bOptVerbose = false; bool bOptDebug = 1; - int iOptZeropad = 0; + int iOptZeropad = 1; int optTrace = TRACE_NONE; double dOptFilterParam = -1; string sOptFilterName (SignalFilter::convertFilterIDToName (SignalFilter::FILTER_ABS_BANDLIMIT)); string sOptFilterMethodName (ProcessSignal::convertFilterMethodIDToName (ProcessSignal::FILTER_METHOD_CONVOLUTION)); - string sOptFilterGenerationName (ProcessSignal::convertFilterGenerationIDToName (ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER)); + string sOptFilterGenerationName (ProcessSignal::convertFilterGenerationIDToName (ProcessSignal::FILTER_GENERATION_DIRECT)); string sOptInterpName (Backprojector::convertInterpIDToName (Backprojector::INTERP_LINEAR)); string sOptBackprojectName (Backprojector::convertBackprojectIDToName (Backprojector::BPROJ_IDIFF3)); int iOptPreinterpolationFactor = 1;