From b361677a2f7d5b443641faec70b057f2a84dc77e Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Sat, 10 Mar 2001 23:14:16 +0000 Subject: [PATCH] r626: no message --- ChangeLog | 4 +- NEWS | 20 +++++++++ include/ezplot.h | 3 +- include/plotfile.h | 74 +++++++++++++++++--------------- include/projections.h | 34 ++++++++++++++- libctgraphics/ezplot.cpp | 24 +++-------- libctgraphics/sgp.cpp | 48 ++++++++++++--------- libctsim/projections.cpp | 90 ++++++++++++++++++++++++++++++++++++--- libctsim/scanner.cpp | 4 +- libctsupport/plotfile.cpp | 6 +-- msvc/ctsim/ctsim.plg | 81 +++++++++++++++++++++++------------ src/ctsim.h | 3 +- src/views.cpp | 82 ++++++++++++++++++++++++++++------- src/views.h | 3 +- 14 files changed, 346 insertions(+), 130 deletions(-) diff --git a/ChangeLog b/ChangeLog index a48e4ce..1467907 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -3.1.0 - Released 2//01 +3.5.0 - Released 2//01 * ctsim: Added tips to be displayed at startup and via the help menu. @@ -17,6 +17,8 @@ * ctsim: Added imagefile export to DICOM files. + * ctsim: Added plot t-theta sampling to projection file menu. + * ctsim: Added background and SMP processing for reconstructions. * ctsim: Added background and SMP processing for scanning. diff --git a/NEWS b/NEWS index 2da1dee..b2837f0 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,23 @@ +Version 3.5 New Features + +* Multithreading for running length processes in background. Also + takes advantage of multiple-CPU's in SMP systems for speed improvements + with parallel processing. + +* Import PNG, PPM, and PGM images + +* DICOM file import/export + +* Can read and reconstruct SIEMENS AR.STAR DICOM raw data files + +* Scattergram of T-Theta sampling. + +* Added startup-tips to help new users learn features. + +* Added ability to place detector at any arbitray position + + + Version 3.0 New Features * Greatly improved dialog boxes diff --git a/include/ezplot.h b/include/ezplot.h index d605f92..797d53c 100644 --- a/include/ezplot.h +++ b/include/ezplot.h @@ -7,7 +7,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ezplot.h,v 1.25 2001/01/28 19:10:18 kevin Exp $ +** $Id: ezplot.h,v 1.26 2001/03/10 23:14:15 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 @@ -84,6 +84,7 @@ enum { SB_BOX, SB_CIRCLE, SB_ERRORBAR, + SB_POINT, MAXSYMBOL, }; diff --git a/include/plotfile.h b/include/plotfile.h index a11c330..ae74b62 100644 --- a/include/plotfile.h +++ b/include/plotfile.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: plotfile.h,v 1.8 2001/01/28 19:10:18 kevin Exp $ +** $Id: plotfile.h,v 1.9 2001/03/10 23:14:15 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 @@ -60,7 +60,7 @@ class PlotFile { - private: +private: std::string m_strFilename; std::string m_strDate; std::vector m_vecStrDescriptions; @@ -68,68 +68,72 @@ class PlotFile std::vector m_vecCurves; int m_iNumColumns; int m_iNumRecords; - + bool m_bScatterPlot; + bool headerRead (std::iostream& os); bool headerWrite (std::iostream& os); bool columnsRead (std::iostream& os); bool columnsWrite (std::iostream& os); - + void initHeaders (); - + PlotFile (const PlotFile& rhs); // copy constructor PlotFile& operator= (const PlotFile&); // assignment operator - + public: PlotFile (int iNColumns, int iNRecords); PlotFile (void); ~PlotFile (); - - void setCurveSize (int iNCurves, int iNRecords); - + + void setCurveSize (int iNCurves, int iNRecords, bool bScatterPlot = false); + void addDescription (const char* const pszDesc) - { m_vecStrDescriptions.push_back (pszDesc); } - + { m_vecStrDescriptions.push_back (pszDesc); } + void addEzsetCommand (const char* const pszCmd) - { m_vecStrEzsetCommands.push_back (pszCmd); } + { m_vecStrEzsetCommands.push_back (pszCmd); } bool addColumn (int iCol, const double* const pdColumn); - + bool addColumn (int iCol, const float* const pdColumn); - + void getColumn (int iCol, double *pdColumnData) const; - + const std::string& getDate () const - { return m_strDate; } - + { return m_strDate; } + int getNumColumns () const - { return m_iNumColumns; } - + { return m_iNumColumns; } + int getNumRecords () const - { return m_iNumRecords; } - + { return m_iNumRecords; } + + bool getIsScatterPlot() const + { return m_bScatterPlot; } + bool getMinMax (int startingCol, double& min, double& max) const; - + bool statistics (int startingCol, double& min, double& max, double& mean, double& mode, double& median, double &stddev) const; - + unsigned int getNumDescriptions (void) const - { return m_vecStrDescriptions.size(); } - + { return m_vecStrDescriptions.size(); } + const std::string& getDescription (int iDescIndex) const - { return m_vecStrDescriptions[iDescIndex]; } - + { return m_vecStrDescriptions[iDescIndex]; } + unsigned int getNumEzsetCommands (void) const - { return m_vecStrEzsetCommands.size(); } - + { return m_vecStrEzsetCommands.size(); } + const std::string& getEzsetCommand (int iIndex) const - { return m_vecStrEzsetCommands[iIndex]; } - + { return m_vecStrEzsetCommands[iIndex]; } + bool fileRead (const char* const filename); - + bool fileWrite (const char* const filename); - + const std::string& getFilename (void) const - { return m_strFilename; } - + { return m_strFilename; } + void printHeaders (std::ostream& os) const; void printHeaders (std::ostringstream& os) const; void printHeadersBrief (std::ostream& os) const; diff --git a/include/projections.h b/include/projections.h index 610cae7..39cb09a 100644 --- a/include/projections.h +++ b/include/projections.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: projections.h,v 1.27 2001/03/02 02:08:14 kevin Exp $ +** $Id: projections.h,v 1.28 2001/03/10 23:14:15 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -38,6 +38,36 @@ class fnetorderstream; #include "imagefile.h" #include +//used for rebinning divergent beam projections to parallel +class ParallelRaysumCoordinate { +public: + double m_dT; // Distance from center of origin + double m_dTheta; // perpendicular angle to origin + int m_iViewNum; // View number for this raysum + int m_iDetNum; // Detector number for this raysum + + bool lessThanT (ParallelRaysumCoordinate& rCompare) + {return m_dT < rCompare.m_dT; } + bool lessThanTheta (ParallelRaysumCoordinate& rCompare) + {return m_dTheta < rCompare.m_dTheta; } +}; + +class ParallelRaysums { +private: + ParallelRaysumCoordinate** m_ppCoordinates; + int m_iNumCoordinates; + +public: + ParallelRaysums (Projections* pProjections); + ~ParallelRaysums (); + + ParallelRaysumCoordinate** getCoordinates() {return m_ppCoordinates;} + int getNumCoordinates() const {return m_iNumCoordinates;} + void getLimits (double* dMinT, double* dMaxT, double* dMinTheta, double* dMaxTheta) const; +}; + + + // Projections class Projections { @@ -74,6 +104,8 @@ class Projections bool detarrayRead (fnetorderstream& fs, DetectorArray& darray, const int view_num); bool detarrayWrite (fnetorderstream& fs, const DetectorArray& darray, const int view_num); + bool interpolateToParallel(); + bool convertPolar (ImageFile& rIF, int iInterpolation); bool convertFFTPolar (ImageFile& rIF, int iInterpolation, int iZeropad); bool calcArrayPolarCoordinates (unsigned int nx, unsigned int ny, double** ppdView, double** ppdDet); diff --git a/libctgraphics/ezplot.cpp b/libctgraphics/ezplot.cpp index ed1ca23..79a4ebb 100644 --- a/libctgraphics/ezplot.cpp +++ b/libctgraphics/ezplot.cpp @@ -6,7 +6,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: ezplot.cpp,v 1.31 2001/02/20 04:48:45 kevin Exp $ +** $Id: ezplot.cpp,v 1.32 2001/03/10 23:14:16 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 @@ -466,14 +466,11 @@ EZPlot::getLegend (unsigned int iCurve) const void EZPlot::plot (SGP* pSGP) { - if (m_vecCurves.size() <= 0) return; - m_pSGP = pSGP; - m_pSGP->setWindow (0., 0., 1., 1.); if (s_textsize == TRUE) @@ -481,6 +478,8 @@ EZPlot::plot (SGP* pSGP) charheight = m_pSGP->getCharHeight(); charwidth = m_pSGP->getCharWidth(); + double symheight = charheight * 0.3; // size of symbol in NDC + double symwidth = symheight; const EZPlotCurve& firstCurve = *m_vecCurves[0]; @@ -668,7 +667,7 @@ EZPlot::plot (SGP* pSGP) m_pSGP->setLineStyle (SGP::LS_SOLID); for (int j = 0; j < 5; j++) { m_pSGP->moveAbs (xmin + j * xinc, y); - symbol(iSymbol, 0.5 * charwidth, 0.5 * charheight); + symbol (iSymbol, symwidth, symheight); } } ++iLegend; // move to next legend position @@ -816,10 +815,6 @@ EZPlot::plot (SGP* pSGP) m_pSGP->setLineStyle (SGP::LS_SOLID); drawAxes(); - // size of symbol in NDC - double symwidth = charwidth; - double symheight = charheight; - double clipRect[4]; @@ -847,27 +842,18 @@ EZPlot::plot (SGP* pSGP) for (int i = 1; i < pCurve->m_iPointCount; i++) { double x2 = convertWorldToNDC_X (pCurve->x[i]); double y2 = convertWorldToNDC_Y (pCurve->y[i]); - double x2Clip = x2; - double y2Clip = y2; if (clip_rect (x1, y1, x2Clip, y2Clip, clipRect)) { - m_pSGP->moveAbs (x1, y1); - m_pSGP->lineAbs (x2Clip, y2Clip); - } - x1 = x2; - y1 = y2; - } } if (iSym > 0) { - int iSymFreq = getSymbolFreq (iCurve); m_pSGP->setLineStyle (SGP::LS_SOLID); double x = convertWorldToNDC_X (pCurve->x[0]); @@ -1144,6 +1130,8 @@ EZPlot::symbol (int sym, double symwidth, double symheight) m_pSGP->moveRel (-0.5 * symwidth, 0.0); m_pSGP->lineRel (symwidth, 0.0); m_pSGP->moveRel (-0.5 * symwidth, 0.5 * symheight); + } else if (sym == SB_POINT) { + m_pSGP->pointRel (0, 0); } } diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp index 275a955..57904a6 100644 --- a/libctgraphics/sgp.cpp +++ b/libctgraphics/sgp.cpp @@ -7,7 +7,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: sgp.cpp,v 1.29 2001/01/28 19:10:18 kevin Exp $ +** $Id: sgp.cpp,v 1.30 2001/03/10 23:14:16 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 @@ -175,6 +175,17 @@ SGP::markerNDC (double x, double y) void SGP::pointNDC (double x, double y) { + int xp = static_cast(x * (m_iPhysicalXSize - 1) + 0.5); + int yp = static_cast(y * (m_iPhysicalYSize - 1) + 0.5); + if (m_driver.isWX()) + yp = m_iPhysicalYSize - yp; + +#if HAVE_WXWINDOWS + if (m_driver.isWX()) + m_driver.idWX()->DrawPoint (xp, yp); +#endif + m_iCurrentPhysicalX = xp; + m_iCurrentPhysicalY = yp; } @@ -657,7 +668,6 @@ SGP::pointAbs (double x, double y) double xndc = x, yndc = y; mc_to_ndc.transformPoint (&xndc, &yndc); pointNDC (xndc, yndc); - stylusNDC (xndc, yndc, false); // move to location m_dCurrentWorldX = x; m_dCurrentWorldY = y; } @@ -746,31 +756,31 @@ SGP::drawArc (const double r, double start, double stop) stop = temp; } - double x = r * cos ((double) start); - double y = r * sin ((double) start); - moveRel (x, y); // move from center to start of arc + double xCent = m_dCurrentWorldX; + double yCent = m_dCurrentWorldY; + + double x = r * cos (start); + double y = r * sin (start); + moveAbs (xCent + x, yCent + y); // move from center to start of arc - const double thetaIncrement = (5 * (TWOPI / 360)); - double cosTheta = cos(thetaIncrement); - double sinTheta = sin(thetaIncrement); + const double thetaIncrement = (5 * (TWOPI / 360)); // 5 degree increments + double cosTheta = cos (thetaIncrement); + double sinTheta = sin (thetaIncrement); - double angle, xp, yp; - for (angle = start; angle < stop - thetaIncrement; angle += thetaIncrement) { - xp = cosTheta * x - sinTheta * y; // translate point by thetaIncrement - yp = sinTheta * x + cosTheta * y; - lineAbs (xp, yp); + for (double angle = start; angle < stop; angle += thetaIncrement) { + double xp = cosTheta * x - sinTheta * y; // translate point by thetaIncrement + double yp = sinTheta * x + cosTheta * y; + lineAbs (xCent + xp, yCent + yp); x = xp; y = yp; } double c = cos (stop - angle); double s = sin (stop - angle); - xp = c * x - s * y; - yp = s * x + c * y; - lineAbs (xp, yp); + double xp = c * x - s * y; + double yp = s * x + c * y; + lineAbs (xCent + xp, yCent + yp); - x = r * cos (stop); - y = r * sin (stop); - moveRel (-x, -y); // move back to center of circle + moveAbs (xCent, yCent); // move back to center of circle } diff --git a/libctsim/projections.cpp b/libctsim/projections.cpp index 627ccb9..b3d6d35 100644 --- a/libctsim/projections.cpp +++ b/libctsim/projections.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: projections.cpp,v 1.54 2001/03/05 21:59:55 kevin Exp $ +** $Id: projections.cpp,v 1.55 2001/03/10 23:14:16 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 @@ -687,6 +687,11 @@ Projections::convertPolar (ImageFile& rIF, int iInterpolationID) if (! v || nx == 0 || ny == 0) return false; + + if (m_geometry != Scanner::GEOMETRY_PARALLEL) { + sys_error (ERR_WARNING, "convertPolar supports Parallel only"); + return false; + } Array2d adView (nx, ny); Array2d adDet (nx, ny); @@ -727,6 +732,11 @@ Projections::convertFFTPolar (ImageFile& rIF, int iInterpolationID, int iZeropad if (! v || nx == 0 || ny == 0) return false; + if (m_geometry != Scanner::GEOMETRY_PARALLEL) { + sys_error (ERR_WARNING, "convertFFTPolar supports Parallel only"); + return false; + } + #ifndef HAVE_FFT return false; #else @@ -784,11 +794,6 @@ Projections::calcArrayPolarCoordinates (unsigned int nx, unsigned int ny, double int iDetCenter = (m_nDet - 1) / 2; // index refering to L=0 projection - if (m_geometry != Scanner::GEOMETRY_PARALLEL) { - sys_error (ERR_WARNING, "convertPolar supports Parallel only"); - return false; - } - // Calculates polar coordinates (view#, det#) for each point on phantom grid double x = xMin + xInc / 2; // Rectang coords of center of pixel for (unsigned int ix = 0; ix < nx; x += xInc, ix++) { @@ -952,7 +957,7 @@ Projections::initFromSomatomAR_STAR (int iNViews, int iNDets, unsigned char* pDa double dTempScale = 2294.4871 * dEScale; for (int id = 0; id < iNDets; id++) { int iV = pData[lDataPos+1] + 256 * pData[lDataPos]; - if (iV > 32767) + if (iV > 32767) // two's complement signed conversion iV = iV - 65536; double dCosScale = cos ((id + 1 - iCenter) * dBetaInc); detval[id] = iV / (dTempScale * dCosScale); @@ -963,3 +968,74 @@ Projections::initFromSomatomAR_STAR (int iNViews, int iNDets, unsigned char* pDa return true; } + +ParallelRaysums::ParallelRaysums (Projections* pProjections) +: m_ppCoordinates(NULL), m_iNumCoordinates(0) +{ + int nDet = pProjections->nDet(); + int nView = pProjections->nView(); + int iGeometry = pProjections->geometry(); + double dDetInc = pProjections->detInc(); + double dDetStart = pProjections->detStart(); + double dFocalLength = pProjections->focalLength(); + + m_iNumCoordinates = nDet * nView; + m_ppCoordinates = new ParallelRaysumCoordinate* [m_iNumCoordinates]; + for (int i = 0; i < m_iNumCoordinates; i++) + m_ppCoordinates[i] = new ParallelRaysumCoordinate; + + ParallelRaysumCoordinate** ppCurrentCoordinate = m_ppCoordinates; + + for (int iV = 0; iV < nView; iV++) { + double dViewAngle = pProjections->getDetectorArray(iV).viewAngle(); + for (int iD = 0; iD < nDet; iD++) { + ParallelRaysumCoordinate* pC = *ppCurrentCoordinate; + if (iGeometry == Scanner::GEOMETRY_PARALLEL) { + pC->m_dTheta = dViewAngle; + pC->m_dT = dDetStart + (iD * dDetInc); + } else if (iGeometry == Scanner::GEOMETRY_EQUILINEAR) { + double dDetPos = dDetStart + (iD * dDetInc); + double dFanAngle = atan (dDetPos / pProjections->sourceDetectorLength()); + pC->m_dTheta = dViewAngle + dFanAngle; + pC->m_dT = dFocalLength * sin(dFanAngle); + } else if (iGeometry == Scanner::GEOMETRY_EQUIANGULAR) { + double dFanAngle = dDetStart + (iD * dDetInc); + pC->m_dTheta = dViewAngle + dFanAngle; + pC->m_dT = dFocalLength * sin(dFanAngle); + } + ++ppCurrentCoordinate; + } + } +} + +ParallelRaysums::~ParallelRaysums() +{ + for (int i = 0; i < m_iNumCoordinates; i++) + delete m_ppCoordinates[i]; + + delete m_ppCoordinates; +} + +void +ParallelRaysums::getLimits (double* dMinT, double* dMaxT, double* dMinTheta, double* dMaxTheta) const +{ + if (m_iNumCoordinates <= 0) + return; + + *dMinT = *dMaxT = m_ppCoordinates[0]->m_dT; + *dMinTheta = *dMaxTheta = m_ppCoordinates[0]->m_dTheta; + + for (int i = 0; i < m_iNumCoordinates; i++) { + double dT = m_ppCoordinates[i]->m_dT; + double dTheta = m_ppCoordinates[i]->m_dTheta; + if (dT < *dMinT) + *dMinT = dT; + else if (dT > *dMaxT) + *dMaxT = dT; + + if (dTheta < *dMinTheta) + *dMinTheta = dTheta; + else if (dTheta > *dMaxTheta) + *dMaxTheta = dTheta; + } +} diff --git a/libctsim/scanner.cpp b/libctsim/scanner.cpp index 2314595..ff3cd9a 100644 --- a/libctsim/scanner.cpp +++ b/libctsim/scanner.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: scanner.cpp,v 1.33 2001/03/01 07:30:49 kevin Exp $ +** $Id: scanner.cpp,v 1.34 2001/03/10 23:14:16 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 @@ -188,8 +188,10 @@ Scanner::Scanner (const Phantom& phm, const char* const geometryName, m_detInc = m_detLen / (m_nDet - 1); // center detector = (nDet/2) dDetectorArrayEndOffset = m_detInc; } + // adjust for center-detector length double dA1 = acos ((m_dScanDiameter / 2) / m_dCenterDetectorLength); double dAngularScale = 2 * (HALFPI + dAngle - dA1) / m_detLen; + m_dAngularDetLen = dAngularScale * (m_detLen + dDetectorArrayEndOffset); m_dAngularDetIncrement = dAngularScale * m_detInc; m_initPos.dAngularDet = -m_dAngularDetLen / 2; diff --git a/libctsupport/plotfile.cpp b/libctsupport/plotfile.cpp index 81682b9..a99bf1d 100644 --- a/libctsupport/plotfile.cpp +++ b/libctsupport/plotfile.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: plotfile.cpp,v 1.12 2001/01/28 19:10:18 kevin Exp $ +** $Id: plotfile.cpp,v 1.13 2001/03/10 23:14:16 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,17 +64,17 @@ PlotFile::initHeaders () } void -PlotFile::setCurveSize (int nCols, int nRecords) +PlotFile::setCurveSize (int nCols, int nRecords, bool bScatterPlot) { m_iNumColumns = nCols; m_iNumRecords = nRecords; + m_bScatterPlot = bScatterPlot; m_vecCurves.clear(); m_vecCurves.reserve (m_iNumColumns * m_iNumRecords); } // Storage format // a Column's records are stored sequentially. It begins at iCol * m_iNumRecords - bool PlotFile::addColumn (int iCol, const double* const pdColData) { diff --git a/msvc/ctsim/ctsim.plg b/msvc/ctsim/ctsim.plg index c45df02..375e102 100644 --- a/msvc/ctsim/ctsim.plg +++ b/msvc/ctsim/ctsim.plg @@ -3,30 +3,67 @@
 

Build Log

---------------------Configuration: ctsim - Win32 Debug-------------------- +--------------------Configuration: libctsim - 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\RSP1B8.tmp" with contents +[ +/nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "..\..\..\wx2.2.5\src\png" /I "..\..\..\wx2.2.5\src\zlib" /I "..\..\INCLUDE" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2.2.5\include" /I "\dicom\ctn\include" /D "_DEBUG" /D "HAVE_WXWIN" /D "HAVE_STRING_H" /D "HAVE_GETOPT_H" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MSVC" /D "HAVE_FFTW" /D "HAVE_PNG" /D "HAVE_SGP" /D "HAVE_WXWINDOWS" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "HAVE_CTN_DICOM" /D VERSION=\"3.1.0\" /FR"Debug/" /Fp"Debug/libctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\ctsim\libctgraphics\ezplot.cpp" +] +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1B8.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1B9.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" /I "\dicom\ctn\include" /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.1.0\" /D "HAVE_CTN_DICOM" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c -"C:\ctsim\src\backgroundmgr.cpp" -"C:\ctsim\src\backgroundsupr.cpp" -"C:\ctsim\src\graph3dview.cpp" -"C:\ctsim\src\threadproj.cpp" -"C:\ctsim\src\threadraster.cpp" -"C:\ctsim\src\threadrecon.cpp" +/nologo /out:"Debug\libctsim.lib" +.\Debug\array2dfile.obj +.\Debug\backprojectors.obj +.\Debug\clip.obj +.\Debug\consoleio.obj +.\Debug\ctndicom.obj +.\Debug\dlgezplot.obj +.\Debug\ezplot.obj +.\Debug\ezset.obj +.\Debug\ezsupport.obj +.\Debug\filter.obj +.\Debug\fnetorderstream.obj +.\Debug\fourier.obj +.\Debug\getopt.obj +.\Debug\getopt1.obj +.\Debug\globalvars.obj +.\Debug\hashtable.obj +.\Debug\imagefile.obj +.\Debug\interpolator.obj +.\Debug\mathfuncs.obj +.\Debug\phantom.obj +.\Debug\plotfile.obj +.\Debug\pol.obj +.\Debug\procsignal.obj +.\Debug\projections.obj +.\Debug\reconstruct.obj +.\Debug\scanner.obj +.\Debug\sgp.obj +.\Debug\strfuncs.obj +.\Debug\syserror.obj +.\Debug\trace.obj +.\Debug\transformmatrix.obj +.\Debug\xform.obj ] -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 "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1B9.tmp" +

Output Window

+Compiling... +ezplot.cpp +Creating library... +

+--------------------Configuration: ctsim - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1BA.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" /I "\dicom\ctn\include" /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.1.0\" /D "HAVE_CTN_DICOM" /D CTSIMVERSION=\"3.0.0alpha5\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c -"C:\ctsim\src\ctsim.cpp" -"C:\ctsim\src\dialogs.cpp" -"C:\ctsim\src\docs.cpp" "C:\ctsim\src\views.cpp" ] -Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP4A.tmp" -Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP4B.tmp" with contents +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1BA.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1BB.tmp" with contents [ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib ctn_lib.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib" /libpath:"\dicom\ctn\winctn\ctn_lib\Debug" .\Debug\backgroundmgr.obj @@ -53,19 +90,9 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\.. \wx2.2.5\lib\zlibd.lib \wx2.2.5\lib\tiffd.lib ] -Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP4B.tmp" +Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP1BB.tmp"

Output Window

Compiling... -backgroundmgr.cpp -backgroundsupr.cpp -threadraster.cpp -graph3dview.cpp -threadproj.cpp -threadrecon.cpp -Compiling... -ctsim.cpp -dialogs.cpp -docs.cpp views.cpp Linking... diff --git a/src/ctsim.h b/src/ctsim.h index ee871cb..7ced875 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.55 2001/03/04 03:14:47 kevin Exp $ +** $Id: ctsim.h,v 1.56 2001/03/10 23:14:16 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 @@ -309,6 +309,7 @@ enum { PJMENU_RECONSTRUCT_FOURIER, PJMENU_CONVERT_POLAR, PJMENU_CONVERT_FFT_POLAR, + PJMENU_PLOT_TTHETA_SAMPLING, IFMENU_FILE_EXPORT, IFMENU_FILE_PROPERTIES, diff --git a/src/views.cpp b/src/views.cpp index 54a12b8..6f55604 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.129 2001/03/07 22:30:16 kevin Exp $ +** $Id: views.cpp,v 1.130 2001/03/10 23:14:16 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 @@ -2277,6 +2277,7 @@ EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP) EVT_MENU(PJMENU_RECONSTRUCT_FOURIER, ProjectionFileView::OnReconstructFourier) EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar) EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar) +EVT_MENU(PJMENU_PLOT_TTHETA_SAMPLING, ProjectionFileView::OnPlotTThetaSampling) END_EVENT_TABLE() ProjectionFileView::ProjectionFileView() @@ -2342,11 +2343,14 @@ ProjectionFileView::OnConvertPolar (wxCommandEvent& event) ImageFileDocument* pPolarDoc = theApp->newImageDoc(); ImageFile* pIF = new ImageFile (m_iDefaultPolarNX, m_iDefaultPolarNY); m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str()); - if (! rProj.convertPolar (*pIF, m_iDefaultPolarInterpolation)) { + + if (! rProj.convertPolar (*pIF, m_iDefaultPolarInterpolation)) { delete pIF; *theApp->getLog() << "Error converting to Polar\n"; return; } + + pPolarDoc = theApp->newImageDoc (); if (! pPolarDoc) { sys_error (ERR_SEVERE, "Unable to create image file"); @@ -2408,6 +2412,43 @@ ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event) } } +void +ProjectionFileView::OnPlotTThetaSampling (wxCommandEvent& event) +{ + Projections& rProj = GetDocument()->getProjections(); + ParallelRaysums parallel (&rProj); + PlotFileDocument* pPlotDoc = theApp->newPlotDoc(); + PlotFile& rPlot = pPlotDoc->getPlotFile(); + ParallelRaysumCoordinate** ppCoord = parallel.getCoordinates(); + double* pdT = new double [parallel.getNumCoordinates()]; + double* pdTheta = new double [parallel.getNumCoordinates()]; + for (int i = 0; i < parallel.getNumCoordinates(); i++) { + pdT[i] = (*ppCoord)->m_dT; + pdTheta[i] = (*ppCoord)->m_dTheta; + ++ppCoord; + } + rPlot.setCurveSize (2, parallel.getNumCoordinates(), true); + rPlot.addEzsetCommand ("title T-Theta Sampling"); + rPlot.addEzsetCommand ("xlabel T"); + rPlot.addEzsetCommand ("ylabel Theta"); + rPlot.addEzsetCommand ("curve 1"); + if (rProj.nDet() < 50 && rProj.nView() < 50) + rPlot.addEzsetCommand ("symbol 1"); // x symbol + else + rPlot.addEzsetCommand ("symbol 6"); // point symbol + rPlot.addEzsetCommand ("noline"); + rPlot.addColumn (0, pdT); + rPlot.addColumn (1, pdTheta); + delete pdT; + delete pdTheta; + if (theApp->getAskDeleteNewDocs()) + pPlotDoc->Modify (true); + pPlotDoc->UpdateAllViews (); + pPlotDoc->getView()->OnUpdate (this, NULL); + pPlotDoc->getView()->getFrame()->Show(true); + return; +} + void ProjectionFileView::OnReconstructFourier (wxCommandEvent& event) { @@ -2590,7 +2631,10 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) wxMenu *convert_menu = new wxMenu; convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L"); convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-M"); - + + wxMenu* analyze_menu = new wxMenu; + analyze_menu->Append (PJMENU_PLOT_TTHETA_SAMPLING, "&Plot T-Theta Sampling\tCtrl-T"); + wxMenu *reconstruct_menu = new wxMenu; reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R", "Reconstruct image using filtered backprojection"); reconstruct_menu->Append (PJMENU_RECONSTRUCT_FOURIER, "&Fourier...\tCtrl-E", "Reconstruct image using inverse Fourier"); @@ -2606,19 +2650,21 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) menu_bar->Append (m_pFileMenu, "&File"); menu_bar->Append (convert_menu, "&Convert"); + menu_bar->Append (analyze_menu, "&Analyze"); menu_bar->Append (reconstruct_menu, "&Reconstruct"); menu_bar->Append (help_menu, "&Help"); subframe->SetMenuBar(menu_bar); subframe->Centre(wxBOTH); - wxAcceleratorEntry accelEntries[5]; + wxAcceleratorEntry accelEntries[6]; accelEntries[0].Set (wxACCEL_CTRL, static_cast('L'), PJMENU_CONVERT_POLAR); accelEntries[1].Set (wxACCEL_CTRL, static_cast('M'), PJMENU_CONVERT_FFT_POLAR); accelEntries[2].Set (wxACCEL_CTRL, static_cast('R'), PJMENU_RECONSTRUCT_FBP); accelEntries[3].Set (wxACCEL_CTRL, static_cast('E'), PJMENU_RECONSTRUCT_FOURIER); accelEntries[4].Set (wxACCEL_CTRL, static_cast('I'), PJMENU_FILE_PROPERTIES); - wxAcceleratorTable accelTable (5, accelEntries); + accelEntries[5].Set (wxACCEL_CTRL, static_cast('T'), PJMENU_PLOT_TTHETA_SAMPLING); + wxAcceleratorTable accelTable (6, accelEntries); subframe->SetAcceleratorTable (accelTable); return subframe; @@ -3002,7 +3048,8 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) const PlotFile& rPlotFile = GetDocument()->getPlotFile(); const int iNColumns = rPlotFile.getNumColumns(); const int iNRecords = rPlotFile.getNumRecords(); - + const bool bScatterPlot = rPlotFile.getIsScatterPlot(); + if (iNColumns > 0 && iNRecords > 0) { if (m_pEZPlot) delete m_pEZPlot; @@ -3025,17 +3072,22 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) m_pEZPlot->ezset("box"); m_pEZPlot->ezset("grid"); - - double* pdXaxis = new double [iNRecords]; - rPlotFile.getColumn (0, pdXaxis); - + + double* pdX = new double [iNRecords]; double* pdY = new double [iNRecords]; - for (int iCol = 1; iCol < iNColumns; iCol++) { - rPlotFile.getColumn (iCol, pdY); - m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords); - } + if (! bScatterPlot) { + rPlotFile.getColumn (0, pdX); - delete pdXaxis; + for (int iCol = 1; iCol < iNColumns; iCol++) { + rPlotFile.getColumn (iCol, pdY); + m_pEZPlot->addCurve (pdX, pdY, iNRecords); + } + } else { + rPlotFile.getColumn (0, pdX); + rPlotFile.getColumn (1, pdY); + m_pEZPlot->addCurve (pdX, pdY, iNRecords); + } + delete pdX; delete pdY; } diff --git a/src/views.h b/src/views.h index 8a4a78a..38ea685 100644 --- a/src/views.h +++ b/src/views.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: views.h,v 1.47 2001/03/01 07:30:49 kevin Exp $ +** $Id: views.h,v 1.48 2001/03/10 23:14:16 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 @@ -240,6 +240,7 @@ public: void OnReconstructFourier (wxCommandEvent& event); void OnConvertPolar (wxCommandEvent& event); void OnConvertFFTPolar (wxCommandEvent& event); + void OnPlotTThetaSampling (wxCommandEvent& event); #if CTSIM_MDI wxDocMDIChildFrame* getFrame() { return m_pFrame; } -- 2.34.1