X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=libctsim%2Fprocsignal.cpp;h=707ee382b96dbc75412ad35115a00c9950dc3830;hp=8156252777e5d3aa0e280a8d52b5d46665f725da;hb=d3fa225aa232e132cc198672c4fc148f96a1ab8c;hpb=1e88cf0f7fa4f690ea9f110e8ed3f2b5338d0a10 diff --git a/libctsim/procsignal.cpp b/libctsim/procsignal.cpp index 8156252..707ee38 100644 --- a/libctsim/procsignal.cpp +++ b/libctsim/procsignal.cpp @@ -7,9 +7,9 @@ ** Date Started: Aug 1984 ** ** This is part of the CTSim program -** Copyright (C) 1983-2000 Kevin Rosenberg +** Copyright (c) 1983-2001 Kevin Rosenberg ** -** $Id: procsignal.cpp,v 1.3 2000/08/25 15:59:13 kevin Exp $ +** $Id: procsignal.cpp,v 1.25 2001/02/11 04:56:37 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -27,6 +27,10 @@ #include "ct.h" +#ifdef HAVE_WXWINDOWS +#include "dlgezplot.h" +#endif + // FilterMethod ID/Names const int ProcessSignal::FILTER_METHOD_INVALID = -1; const int ProcessSignal::FILTER_METHOD_CONVOLUTION = 0; @@ -40,7 +44,7 @@ const int ProcessSignal::FILTER_METHOD_RFFTW =5 ; const char* ProcessSignal::s_aszFilterMethodName[] = { {"convolution"}, {"fourier"}, - {"fouier_table"}, + {"fouier-table"}, {"fft"}, #if HAVE_FFTW {"fftw"}, @@ -65,7 +69,7 @@ const int ProcessSignal::FILTER_GENERATION_DIRECT = 0; const int ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER = 1; const char* ProcessSignal::s_aszFilterGenerationName[] = { {"direct"}, - {"inverse_fourier"}, + {"inverse-fourier"}, }; const char* ProcessSignal::s_aszFilterGenerationTitle[] = { {"Direct"}, @@ -77,8 +81,11 @@ 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, int iPreinterpolationFactor, int iTraceLevel) - : m_adFourierCosTable(NULL), m_adFourierSinTable(NULL), m_adFilter(NULL), m_fail(false) +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, + int iGeometry, double dFocalLength, SGP* pSGP) + : m_adFourierCosTable(NULL), m_adFourierSinTable(NULL), m_adFilter(NULL), m_fail(false) { m_idFilterMethod = convertFilterMethodNameToID (szFilterMethodName); if (m_idFilterMethod == FILTER_METHOD_INVALID) { @@ -108,18 +115,26 @@ ProcessSignal::ProcessSignal (const char* szFilterName, const char* szFilterMeth m_failMessage += szDomainName; return; } - - init (m_idFilter, m_idFilterMethod, dBandwidth, dSignalIncrement, nSignalPoints, dFilterParam, m_idDomain, m_idFilterGeneration, iZeropad, iPreinterpolationFactor, iTraceLevel); + + init (m_idFilter, m_idFilterMethod, dBandwidth, dSignalIncrement, nSignalPoints, dFilterParam, m_idDomain, + m_idFilterGeneration, iZeropad, iPreinterpolationFactor, iTraceLevel, iGeometry, dFocalLength, pSGP); } void -ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandwidth, double dSignalIncrement, int nSignalPoints, double dFilterParam, const int idDomain, const int idFilterGeneration, const int iZeropad, const int iPreinterpolationFactor, int iTraceLevel) +ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandwidth, double dSignalIncrement, + int nSignalPoints, double dFilterParam, const int idDomain, const int idFilterGeneration, + const int iZeropad, const int iPreinterpolationFactor, int iTraceLevel, int iGeometry, + double dFocalLength, SGP* pSGP) { + int i; m_idFilter = idFilter; m_idDomain = idDomain; m_idFilterMethod = idFilterMethod; m_idFilterGeneration = idFilterGeneration; + m_idGeometry = iGeometry; + m_dFocalLength = dFocalLength; + if (m_idFilter == SignalFilter::FILTER_INVALID || m_idDomain == SignalFilter::DOMAIN_INVALID || m_idFilterMethod == FILTER_METHOD_INVALID || m_idFilterGeneration == FILTER_GENERATION_INVALID) { m_fail = true; return; @@ -133,7 +148,15 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw m_dFilterParam = dFilterParam; m_iZeropad = iZeropad; m_iPreinterpolationFactor = iPreinterpolationFactor; - + + // scale signalInc/BW to signalInc/2 to adjust for imaginary detector + // through origin of phantom rather than 2 times distance to detector, + // see Kak-Slaney Fig 3.22, for Collinear diagram + if (m_idGeometry == Scanner::GEOMETRY_EQUILINEAR) { + m_dSignalInc /= 2; + m_dBandwidth *= 2; + } + if (m_idFilterMethod == FILTER_METHOD_FFT) { #if HAVE_FFTW m_idFilterMethod = FILTER_METHOD_RFFTW; @@ -143,140 +166,170 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw return; #endif } - + bool m_bFrequencyFiltering = true; if (m_idFilterMethod == FILTER_METHOD_CONVOLUTION) m_bFrequencyFiltering = false; - + // Spatial-based filtering if (! m_bFrequencyFiltering) { - + if (m_idFilterGeneration == FILTER_GENERATION_DIRECT) { - m_nFilterPoints = 2 * (m_nSignalPoints - 1) + 1; - m_dFilterMin = -m_dSignalInc * (m_nSignalPoints - 1); - m_dFilterMax = m_dSignalInc * (m_nSignalPoints - 1); - m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); - SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_SPATIAL); - m_adFilter = new double[ m_nFilterPoints ]; - filter.copyFilterData (m_adFilter, 0, m_nFilterPoints); + m_nFilterPoints = 2 * (m_nSignalPoints - 1) + 1; + m_dFilterMin = -m_dSignalInc * (m_nSignalPoints - 1); + m_dFilterMax = m_dSignalInc * (m_nSignalPoints - 1); + m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); + SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_SPATIAL); + m_adFilter = new double[ m_nFilterPoints ]; + filter.copyFilterData (m_adFilter, 0, m_nFilterPoints); } else if (m_idFilterGeneration == FILTER_GENERATION_INVERSE_FOURIER) { - m_nFilterPoints = 2 * (m_nSignalPoints - 1) + 1; - m_dFilterMin = -1. / (2 * m_dSignalInc); - m_dFilterMax = 1. / (2 * m_dSignalInc); - m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); - SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_FREQUENCY); - m_adFilter = new double[ m_nFilterPoints ]; - double adFrequencyFilter [m_nFilterPoints]; - filter.copyFilterData (adFrequencyFilter, 0, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Frequency Filter: Natural Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Filter Response: Natural Order"); - ezplot.addCurve (adFrequencyFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); - } - - shuffleNaturalToFourierOrder (adFrequencyFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Frequency Filter: Fourier Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Filter Response: Fourier Order"); - ezplot.addCurve (adFrequencyFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); - } - ProcessSignal::finiteFourierTransform (adFrequencyFilter, m_adFilter, m_nFilterPoints, -1); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Inverse Fourier Frequency: Fourier Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Inverse Fourier Frequency: Fourier Order"); - ezplot.addCurve (m_adFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); - } - shuffleFourierToNaturalOrder (m_adFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Inverse Fourier Frequency: Natural Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Inverse Fourier Frequency: Natural Order"); - ezplot.addCurve (m_adFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); - } - for (int i = 0; i < m_nFilterPoints; i++) { - m_adFilter[i] /= m_dSignalInc; - } + m_nFilterPoints = 2 * (m_nSignalPoints - 1) + 1; + m_dFilterMin = -1. / (2 * m_dSignalInc); + m_dFilterMax = 1. / (2 * m_dSignalInc); + m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); + SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_FREQUENCY); + m_adFilter = new double[ m_nFilterPoints ]; + double* adFrequencyFilter = new double [m_nFilterPoints]; + filter.copyFilterData (adFrequencyFilter, 0, m_nFilterPoints); +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Filter Response: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (adFrequencyFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + Fourier::shuffleNaturalToFourierOrder (adFrequencyFilter, m_nFilterPoints); +#ifdef HAVE_SGP + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Filter Response: Fourier Order"); + dlgEZPlot.getEZPlot()->addCurve (adFrequencyFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + ProcessSignal::finiteFourierTransform (adFrequencyFilter, m_adFilter, m_nFilterPoints, FORWARD); + delete adFrequencyFilter; +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Inverse Fourier Frequency: Fourier Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + Fourier::shuffleFourierToNaturalOrder (m_adFilter, m_nFilterPoints); +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Inverse Fourier Frequency: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + for (i = 0; i < m_nFilterPoints; i++) { + m_adFilter[i] /= m_dSignalInc; + } } - } - - // Frequency-based filtering - else if (m_bFrequencyFiltering) { - + if (m_idGeometry == Scanner::GEOMETRY_EQUILINEAR) { + for (i = 0; i < m_nFilterPoints; i++) + m_adFilter[i] *= 0.5; + } else if (m_idGeometry == Scanner::GEOMETRY_EQUIANGULAR) { + for (i = 0; i < m_nFilterPoints; i++) { + int iDetFromZero = i - ((m_nFilterPoints - 1) / 2); + double sinScale = 1 / SignalFilter::sinc (iDetFromZero * m_dSignalInc); + double dScale = 0.5 * sinScale * sinScale; + m_adFilter[i] *= dScale; + } +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Scaled Inverse Fourier Frequency: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + } // if (geometry) + } // if (spatial filtering) + + else if (m_bFrequencyFiltering) { // Frequency-based filtering + if (m_idFilterGeneration == FILTER_GENERATION_DIRECT) { // calculate number of filter points with zeropadding m_nFilterPoints = m_nSignalPoints; if (m_iZeropad > 0) { - double logBase2 = log(m_nFilterPoints) / log(2); - int nextPowerOf2 = static_cast(floor(logBase2)); - if (logBase2 != floor(logBase2)) - nextPowerOf2++; - nextPowerOf2 += (m_iZeropad - 1); - m_nFilterPoints = 1 << nextPowerOf2; - if (m_traceLevel >= TRACE_TEXT) - cout << "nFilterPoints = " << m_nFilterPoints << endl; + double logBase2 = log(m_nFilterPoints) / log(2); + int nextPowerOf2 = static_cast(floor(logBase2)); + if (logBase2 != floor(logBase2)) + nextPowerOf2++; + nextPowerOf2 += (m_iZeropad - 1); + m_nFilterPoints = 1 << nextPowerOf2; +#if defined(DEBUG) || defined(_DEBUG) + if (m_traceLevel >= Trace::TRACE_CONSOLE) + sys_error (ERR_TRACE, "nFilterPoints = %d", m_nFilterPoints); +#endif } m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor; - + if (m_nFilterPoints % 2) { // Odd - m_dFilterMin = -1. / (2 * m_dSignalInc); - m_dFilterMax = 1. / (2 * m_dSignalInc); - m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); + m_dFilterMin = -1. / (2 * m_dSignalInc); + m_dFilterMax = 1. / (2 * m_dSignalInc); + m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (m_nFilterPoints - 1); } else { // Even - m_dFilterMin = -1. / (2 * m_dSignalInc); - m_dFilterMax = 1. / (2 * m_dSignalInc); - m_dFilterInc = (m_dFilterMax - m_dFilterMin) / m_nFilterPoints; - m_dFilterMax -= m_dFilterInc; + m_dFilterMin = -1. / (2 * m_dSignalInc); + m_dFilterMax = 1. / (2 * m_dSignalInc); + m_dFilterInc = (m_dFilterMax - m_dFilterMin) / m_nFilterPoints; + m_dFilterMax -= m_dFilterInc; } - - SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_FREQUENCY); + + SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, m_nFilterPoints, m_dBandwidth, + m_dFilterParam, SignalFilter::DOMAIN_FREQUENCY); m_adFilter = new double [m_nFilterPoints]; filter.copyFilterData (m_adFilter, 0, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Frequency Filter: Natural Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Filter Filter: Natural Order"); - ezplot.addCurve (m_adFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); + +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Frequency Filter: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + + // This works fairly well. I'm not sure why since scaling for geometries is done on + // frequency filter rather than spatial filter as it should be. + // It gives values slightly off than freq/inverse filtering + if (m_idGeometry == Scanner::GEOMETRY_EQUILINEAR) { + for (i = 0; i < m_nFilterPoints; i++) + m_adFilter[i] *= 0.5; + } else if (m_idGeometry == Scanner::GEOMETRY_EQUIANGULAR) { + for (i = 0; i < m_nFilterPoints; i++) { + int iDetFromZero = i - ((m_nFilterPoints - 1) / 2); + double sinScale = 1 / SignalFilter::sinc (iDetFromZero * m_dSignalInc); + double dScale = 0.5 * sinScale * sinScale; + m_adFilter[i] *= dScale; + } + } +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Filter Geometry Scaled: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); } - shuffleNaturalToFourierOrder (m_adFilter, m_nFilterPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Frequency Filter: Fourier Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Filter Filter: Fourier Order"); - ezplot.addCurve (m_adFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); - } +#endif + Fourier::shuffleNaturalToFourierOrder (m_adFilter, m_nFilterPoints); +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Filter Geometry Scaled: Fourier Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); + } +#endif + + // FILTERING: FREQUENCY - INVERSE FOURIER + } else if (m_idFilterGeneration == FILTER_GENERATION_INVERSE_FOURIER) { // calculate number of filter points with zeropadding int nSpatialPoints = 2 * (m_nSignalPoints - 1) + 1; @@ -285,87 +338,110 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw m_dFilterInc = (m_dFilterMax - m_dFilterMin) / (nSpatialPoints - 1); m_nFilterPoints = nSpatialPoints; if (m_iZeropad > 0) { - double logBase2 = log(nSpatialPoints) / log(2); - int nextPowerOf2 = static_cast(floor(logBase2)); - if (logBase2 != floor(logBase2)) - nextPowerOf2++; - nextPowerOf2 += (m_iZeropad - 1); - m_nFilterPoints = 1 << nextPowerOf2; + double logBase2 = log(nSpatialPoints) / log(2); + int nextPowerOf2 = static_cast(floor(logBase2)); + if (logBase2 != floor(logBase2)) + nextPowerOf2++; + nextPowerOf2 += (m_iZeropad - 1); + m_nFilterPoints = 1 << nextPowerOf2; } m_nOutputPoints = m_nFilterPoints * m_iPreinterpolationFactor; - if (m_traceLevel >= TRACE_TEXT) - cout << "nFilterPoints = " << m_nFilterPoints << endl; - double adSpatialFilter [m_nFilterPoints]; - SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, nSpatialPoints, m_dBandwidth, m_dFilterParam, SignalFilter::DOMAIN_SPATIAL); +#if defined(DEBUG) || defined(_DEBUG) + if (m_traceLevel >= Trace::TRACE_CONSOLE) + sys_error (ERR_TRACE, "nFilterPoints = %d", m_nFilterPoints); +#endif + double* adSpatialFilter = new double [m_nFilterPoints]; + SignalFilter filter (m_idFilter, m_dFilterMin, m_dFilterMax, nSpatialPoints, m_dBandwidth, + m_dFilterParam, SignalFilter::DOMAIN_SPATIAL); filter.copyFilterData (adSpatialFilter, 0, nSpatialPoints); - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Spatial Filter: Natural Order"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Spatial Filter: Natural Order"); - ezplot.addCurve (adSpatialFilter, nSpatialPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot;; + dlgEZPlot.getEZPlot()->ezset ("title Spatial Filter: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (adSpatialFilter, nSpatialPoints); + dlgEZPlot.ShowModal(); } - for (int i = nSpatialPoints; i < m_nFilterPoints; i++) - adSpatialFilter[i] = 0; - +#endif + + if (m_idGeometry == Scanner::GEOMETRY_EQUILINEAR) { + for (i = 0; i < nSpatialPoints; i++) + adSpatialFilter[i] *= 0.5; + } else if (m_idGeometry == Scanner::GEOMETRY_EQUIANGULAR) { + for (i = 0; i < nSpatialPoints; i++) { + int iDetFromZero = i - ((nSpatialPoints - 1) / 2); + double sinScale = sin (iDetFromZero * m_dSignalInc); + if (fabs(sinScale) < 1E-7) + sinScale = 1; + else + sinScale = (iDetFromZero * m_dSignalInc) / sinScale; + double dScale = 0.5 * sinScale * sinScale; + adSpatialFilter[i] *= dScale; + } + } +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot;; + dlgEZPlot.getEZPlot()->ezset ("title Scaled Spatial Filter: Natural Order"); + dlgEZPlot.getEZPlot()->addCurve (adSpatialFilter, nSpatialPoints); + dlgEZPlot.ShowModal(); + } +#endif + for (i = nSpatialPoints; i < m_nFilterPoints; i++) + adSpatialFilter[i] = 0; + m_adFilter = new double [m_nFilterPoints]; - complex acInverseFilter [m_nFilterPoints]; - finiteFourierTransform (adSpatialFilter, acInverseFilter, m_nFilterPoints, 1); - for (int i = 0; i < m_nFilterPoints; i++) - m_adFilter[i] = abs(acInverseFilter[i]) * m_dSignalInc; - if (m_traceLevel >= TRACE_PLOT) { - SGPDriver sgpDriver ("Spatial Filter: Inverse"); - SGP sgp (sgpDriver); - EZPlot ezplot (sgp); - - ezplot.ezset ("title Spatial Filter: Inverse"); - ezplot.addCurve (m_adFilter, m_nFilterPoints); - ezplot.plot(); - cio_put_str ("Press any key to continue"); - cio_kb_getc (); + std::complex* acInverseFilter = new std::complex [m_nFilterPoints]; + finiteFourierTransform (adSpatialFilter, acInverseFilter, m_nFilterPoints, BACKWARD); + delete adSpatialFilter; + for (i = 0; i < m_nFilterPoints; i++) + m_adFilter[i] = std::abs (acInverseFilter[i]) * m_dSignalInc; + delete acInverseFilter; +#if defined(HAVE_WXWINDOWS) && (defined(DEBUG) || defined(_DEBUG)) + if (g_bRunningWXWindows && m_traceLevel > 0) { + EZPlotDialog dlgEZPlot; + dlgEZPlot.getEZPlot()->ezset ("title Fourier Scaled Spatial Filter: Fourier Order"); + dlgEZPlot.getEZPlot()->addCurve (m_adFilter, m_nFilterPoints); + dlgEZPlot.ShowModal(); } +#endif } } // precalculate sin and cosine tables for fourier transform if (m_idFilterMethod == FILTER_METHOD_FOURIER_TABLE) { - int nFourier = max(m_nFilterPoints,m_nOutputPoints) * max(m_nFilterPoints, m_nOutputPoints) + 1; + int nFourier = imax (m_nFilterPoints,m_nOutputPoints) * imax (m_nFilterPoints, m_nOutputPoints) + 1; double angleIncrement = (2. * PI) / m_nFilterPoints; m_adFourierCosTable = new double[ nFourier ]; m_adFourierSinTable = new double[ nFourier ]; double angle = 0; - for (int i = 0; i < nFourier; i++) { + for (i = 0; i < nFourier; i++) { m_adFourierCosTable[i] = cos (angle); m_adFourierSinTable[i] = sin (angle); angle += angleIncrement; } } - + #if HAVE_FFTW if (m_idFilterMethod == FILTER_METHOD_FFTW || m_idFilterMethod == FILTER_METHOD_RFFTW) { - for (int i = 0; i < m_nFilterPoints; i++) //fftw uses unnormalized fft + for (i = 0; i < m_nFilterPoints; i++) //fftw uses unnormalized fft m_adFilter[i] /= m_nFilterPoints; } - + if (m_idFilterMethod == FILTER_METHOD_RFFTW) { m_realPlanForward = rfftw_create_plan (m_nFilterPoints, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); m_realPlanBackward = rfftw_create_plan (m_nOutputPoints, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); m_adRealFftInput = new fftw_real [ m_nFilterPoints ]; m_adRealFftSignal = new fftw_real [ m_nOutputPoints ]; - for (int i = 0; i < m_nFilterPoints; i++) + for (i = 0; i < m_nFilterPoints; i++) m_adRealFftInput[i] = 0; } else if (m_idFilterMethod == FILTER_METHOD_FFTW) { m_complexPlanForward = fftw_create_plan (m_nFilterPoints, FFTW_FORWARD, FFTW_ESTIMATE); m_complexPlanBackward = fftw_create_plan (m_nOutputPoints, FFTW_BACKWARD, FFTW_ESTIMATE); m_adComplexFftInput = new fftw_complex [ m_nFilterPoints ]; m_adComplexFftSignal = new fftw_complex [ m_nOutputPoints ]; - for (int i = 0; i < m_nFilterPoints; i++) + for (i = 0; i < m_nFilterPoints; i++) m_adComplexFftInput[i].re = m_adComplexFftInput[i].im = 0; - for (int i = 0; i < m_nOutputPoints; i++) + for (i = 0; i < m_nOutputPoints; i++) m_adComplexFftSignal[i].re = m_adComplexFftSignal[i].im = 0; } #endif @@ -374,23 +450,23 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw ProcessSignal::~ProcessSignal (void) { - delete [] m_adFourierSinTable; - delete [] m_adFourierCosTable; - delete [] m_adFilter; - + delete [] m_adFourierSinTable; + delete [] m_adFourierCosTable; + delete [] m_adFilter; + #if HAVE_FFTW - if (m_idFilterMethod == FILTER_METHOD_FFTW) { - fftw_destroy_plan(m_complexPlanForward); - fftw_destroy_plan(m_complexPlanBackward); - delete [] m_adComplexFftInput; - delete [] m_adComplexFftSignal; - } - if (m_idFilterMethod == FILTER_METHOD_RFFTW) { - rfftw_destroy_plan(m_realPlanForward); - rfftw_destroy_plan(m_realPlanBackward); - delete [] m_adRealFftInput; - delete [] m_adRealFftSignal; - } + if (m_idFilterMethod == FILTER_METHOD_FFTW) { + fftw_destroy_plan(m_complexPlanForward); + fftw_destroy_plan(m_complexPlanBackward); + delete [] m_adComplexFftInput; + delete [] m_adComplexFftSignal; + } + if (m_idFilterMethod == FILTER_METHOD_RFFTW) { + rfftw_destroy_plan(m_realPlanForward); + rfftw_destroy_plan(m_realPlanBackward); + delete [] m_adRealFftInput; + delete [] m_adRealFftSignal; + } #endif } @@ -398,24 +474,24 @@ int ProcessSignal::convertFilterMethodNameToID (const char* const filterMethodName) { int fmID = FILTER_METHOD_INVALID; - + for (int i = 0; i < s_iFilterMethodCount; i++) - if (strcasecmp (filterMethodName, s_aszFilterMethodName[i]) == 0) { + if (strcasecmp (filterMethodName, s_aszFilterMethodName[i]) == 0) { fmID = i; break; } - - return (fmID); + + return (fmID); } const char * ProcessSignal::convertFilterMethodIDToName (const int fmID) { static const char *name = ""; - + if (fmID >= 0 && fmID < s_iFilterMethodCount) - return (s_aszFilterMethodName [fmID]); - + return (s_aszFilterMethodName [fmID]); + return (name); } @@ -423,10 +499,10 @@ const char * ProcessSignal::convertFilterMethodIDToTitle (const int fmID) { static const char *title = ""; - + if (fmID >= 0 && fmID < s_iFilterMethodCount) - return (s_aszFilterMethodTitle [fmID]); - + return (s_aszFilterMethodTitle [fmID]); + return (title); } @@ -435,24 +511,24 @@ int ProcessSignal::convertFilterGenerationNameToID (const char* const fgName) { int fgID = FILTER_GENERATION_INVALID; - + for (int i = 0; i < s_iFilterGenerationCount; i++) - if (strcasecmp (fgName, s_aszFilterGenerationName[i]) == 0) { + if (strcasecmp (fgName, s_aszFilterGenerationName[i]) == 0) { fgID = i; break; } - - return (fgID); + + return (fgID); } const char * ProcessSignal::convertFilterGenerationIDToName (const int fgID) { static const char *name = ""; - + if (fgID >= 0 && fgID < s_iFilterGenerationCount) - return (s_aszFilterGenerationName [fgID]); - + return (s_aszFilterGenerationName [fgID]); + return (name); } @@ -460,114 +536,141 @@ const char * ProcessSignal::convertFilterGenerationIDToTitle (const int fgID) { static const char *name = ""; - + if (fgID >= 0 && fgID < s_iFilterGenerationCount) - return (s_aszFilterGenerationTitle [fgID]); - + return (s_aszFilterGenerationTitle [fgID]); + return (name); } void -ProcessSignal::filterSignal (const float input[], double output[]) const +ProcessSignal::filterSignal (const float constInput[], double output[]) const { + double* input = new double [m_nSignalPoints]; + int i; + for (i = 0; i < m_nSignalPoints; i++) + input[i] = constInput[i]; + + if (m_idGeometry == Scanner::GEOMETRY_EQUILINEAR) { + for (int i = 0; i < m_nSignalPoints; i++) { + int iDetFromCenter = i - (m_nSignalPoints / 2); + input[i] *= m_dFocalLength / sqrt (m_dFocalLength * m_dFocalLength + iDetFromCenter * iDetFromCenter * m_dSignalInc * m_dSignalInc); + } + } else if (m_idGeometry == Scanner::GEOMETRY_EQUIANGULAR) { + for (int i = 0; i < m_nSignalPoints; i++) { + int iDetFromCenter = i - (m_nSignalPoints / 2); + input[i] *= m_dFocalLength * cos (iDetFromCenter * m_dSignalInc); + } + } if (m_idFilterMethod == FILTER_METHOD_CONVOLUTION) { - for (int i = 0; i < m_nSignalPoints; i++) + for (i = 0; i < m_nSignalPoints; i++) output[i] = convolve (input, m_dSignalInc, i, m_nSignalPoints); } else if (m_idFilterMethod == FILTER_METHOD_FOURIER) { - double inputSignal[m_nFilterPoints]; - for (int i = 0; i < m_nSignalPoints; i++) + double* inputSignal = new double [m_nFilterPoints]; + for (i = 0; i < m_nSignalPoints; i++) inputSignal[i] = input[i]; - for (int i = m_nSignalPoints; i < m_nFilterPoints; i++) + for (i = m_nSignalPoints; i < m_nFilterPoints; i++) inputSignal[i] = 0; // zeropad - complex fftSignal[m_nFilterPoints]; - finiteFourierTransform (inputSignal, fftSignal, m_nFilterPoints, -1); - for (int i = 0; i < m_nFilterPoints; i++) + std::complex* fftSignal = new std::complex [m_nFilterPoints]; + finiteFourierTransform (inputSignal, fftSignal, m_nFilterPoints, FORWARD); + delete inputSignal; + for (i = 0; i < m_nFilterPoints; i++) fftSignal[i] *= m_adFilter[i]; - double inverseFourier[m_nFilterPoints]; - finiteFourierTransform (fftSignal, inverseFourier, m_nFilterPoints, 1); - for (int i = 0; i < m_nSignalPoints; i++) + double* inverseFourier = new double [m_nFilterPoints]; + finiteFourierTransform (fftSignal, inverseFourier, m_nFilterPoints, BACKWARD); + delete fftSignal; + for (i = 0; i < m_nSignalPoints; i++) output[i] = inverseFourier[i]; + delete inverseFourier; } else if (m_idFilterMethod == FILTER_METHOD_FOURIER_TABLE) { - double inputSignal[m_nFilterPoints]; - for (int i = 0; i < m_nSignalPoints; i++) + double* inputSignal = new double [m_nFilterPoints]; + for (i = 0; i < m_nSignalPoints; i++) inputSignal[i] = input[i]; - for (int i = m_nSignalPoints; i < m_nFilterPoints; i++) + for (i = m_nSignalPoints; i < m_nFilterPoints; i++) inputSignal[i] = 0; // zeropad - complex fftSignal[m_nFilterPoints]; - finiteFourierTransform (inputSignal, fftSignal, -1); - for (int i = 0; i < m_nFilterPoints; i++) + std::complex* fftSignal = new std::complex [m_nFilterPoints]; + finiteFourierTransform (inputSignal, fftSignal, FORWARD); + delete inputSignal; + for (i = 0; i < m_nFilterPoints; i++) fftSignal[i] *= m_adFilter[i]; - double inverseFourier[m_nFilterPoints]; - finiteFourierTransform (fftSignal, inverseFourier, 1); - for (int i = 0; i < m_nSignalPoints; i++) + double* inverseFourier = new double [m_nFilterPoints]; + finiteFourierTransform (fftSignal, inverseFourier, BACKWARD); + delete fftSignal; + for (i = 0; i < m_nSignalPoints; i++) output[i] = inverseFourier[i]; + delete inverseFourier; } #if HAVE_FFTW else if (m_idFilterMethod == FILTER_METHOD_RFFTW) { - for (int i = 0; i < m_nSignalPoints; i++) - m_adRealFftInput[i] = input[i]; - - fftw_real fftOutput [ m_nFilterPoints ]; - rfftw_one (m_realPlanForward, m_adRealFftInput, fftOutput); - for (int i = 0; i < m_nFilterPoints; i++) - m_adRealFftSignal[i] = m_adFilter[i] * fftOutput[i]; - for (int i = m_nFilterPoints; i < m_nOutputPoints; i++) - m_adRealFftSignal[i] = 0; - - fftw_real ifftOutput [ m_nOutputPoints ]; - rfftw_one (m_realPlanBackward, m_adRealFftSignal, ifftOutput); - for (int i = 0; i < m_nSignalPoints * m_iPreinterpolationFactor; i++) - output[i] = ifftOutput[i]; + for (i = 0; i < m_nSignalPoints; i++) + m_adRealFftInput[i] = input[i]; + + fftw_real* fftOutput = new fftw_real [ m_nFilterPoints ]; + rfftw_one (m_realPlanForward, m_adRealFftInput, fftOutput); + for (i = 0; i < m_nFilterPoints; i++) + m_adRealFftSignal[i] = m_adFilter[i] * fftOutput[i]; + delete [] fftOutput; + for (i = m_nFilterPoints; i < m_nOutputPoints; i++) + m_adRealFftSignal[i] = 0; + + fftw_real* ifftOutput = new fftw_real [ m_nOutputPoints ]; + rfftw_one (m_realPlanBackward, m_adRealFftSignal, ifftOutput); + for (i = 0; i < m_nSignalPoints * m_iPreinterpolationFactor; i++) + output[i] = ifftOutput[i]; + delete [] ifftOutput; } else if (m_idFilterMethod == FILTER_METHOD_FFTW) { - for (int i = 0; i < m_nSignalPoints; i++) - m_adComplexFftInput[i].re = input[i]; - - fftw_complex fftOutput [ m_nFilterPoints ]; - fftw_one (m_complexPlanForward, m_adComplexFftInput, fftOutput); - for (int i = 0; i < m_nFilterPoints; i++) { - m_adComplexFftSignal[i].re = m_adFilter[i] * fftOutput[i].re; - m_adComplexFftSignal[i].im = m_adFilter[i] * fftOutput[i].im; - } - fftw_complex ifftOutput [ m_nOutputPoints ]; - fftw_one (m_complexPlanBackward, m_adComplexFftSignal, ifftOutput); - for (int i = 0; i < m_nSignalPoints * m_iPreinterpolationFactor; i++) - output[i] = ifftOutput[i].re; + for (i = 0; i < m_nSignalPoints; i++) + m_adComplexFftInput[i].re = input[i]; + + fftw_complex* fftOutput = new fftw_complex [ m_nFilterPoints ]; + fftw_one (m_complexPlanForward, m_adComplexFftInput, fftOutput); + for (i = 0; i < m_nFilterPoints; i++) { + m_adComplexFftSignal[i].re = m_adFilter[i] * fftOutput[i].re; + m_adComplexFftSignal[i].im = m_adFilter[i] * fftOutput[i].im; + } + delete [] fftOutput; + fftw_complex* ifftOutput = new fftw_complex [ m_nOutputPoints ]; + fftw_one (m_complexPlanBackward, m_adComplexFftSignal, ifftOutput); + for (i = 0; i < m_nSignalPoints * m_iPreinterpolationFactor; i++) + output[i] = ifftOutput[i].re; + delete [] ifftOutput; } #endif + delete input; } /* NAME - * convolve Discrete convolution of two functions - * - * SYNOPSIS - * r = convolve (f1, f2, dx, n, np, func_type) - * double r Convolved result - * double f1[], f2[] Functions to be convolved - * double dx Difference between successive x values - * int n Array index to center convolution about - * int np Number of points in f1 array - * int func_type EVEN or ODD or EVEN_AND_ODD function f2 - * - * NOTES - * f1 is the projection data, its indices range from 0 to np - 1. - * The index for f2, the filter, ranges from -(np-1) to (np-1). - * There are 3 ways to handle the negative vertices of f2: - * 1. If we know f2 is an EVEN function, then f2[-n] = f2[n]. - * All filters used in reconstruction are even. - * 2. If we know f2 is an ODD function, then f2[-n] = -f2[n] - * 3. If f2 is both ODD AND EVEN, then we must store the value of f2 - * for negative indices. Since f2 must range from -(np-1) to (np-1), - * if we add (np - 1) to f2's array index, then f2's index will - * range from 0 to 2 * (np - 1), and the origin, x = 0, will be - * stored at f2[np-1]. - */ +* convolve Discrete convolution of two functions +* +* SYNOPSIS +* r = convolve (f1, f2, dx, n, np, func_type) +* double r Convolved result +* double f1[], f2[] Functions to be convolved +* double dx Difference between successive x values +* int n Array index to center convolution about +* int np Number of points in f1 array +* int func_type EVEN or ODD or EVEN_AND_ODD function f2 +* +* NOTES +* f1 is the projection data, its indices range from 0 to np - 1. +* The index for f2, the filter, ranges from -(np-1) to (np-1). +* There are 3 ways to handle the negative vertices of f2: +* 1. If we know f2 is an EVEN function, then f2[-n] = f2[n]. +* All filters used in reconstruction are even. +* 2. If we know f2 is an ODD function, then f2[-n] = -f2[n] +* 3. If f2 is both ODD AND EVEN, then we must store the value of f2 +* for negative indices. Since f2 must range from -(np-1) to (np-1), +* if we add (np - 1) to f2's array index, then f2's index will +* range from 0 to 2 * (np - 1), and the origin, x = 0, will be +* stored at f2[np-1]. +*/ double ProcessSignal::convolve (const double func[], const double dx, const int n, const int np) const { double sum = 0.0; - + #if UNOPTIMIZED_CONVOLUTION for (int i = 0; i < np; i++) sum += func[i] * m_adFilter[n - i + (np - 1)]; @@ -576,7 +679,7 @@ ProcessSignal::convolve (const double func[], const double dx, const int n, cons for (int i = 0; i < np; i++) sum += *func++ * *f2--; #endif - + return (sum * dx); } @@ -585,16 +688,16 @@ double ProcessSignal::convolve (const float func[], const double dx, const int n, const int np) const { double sum = 0.0; - + #if UNOPTIMIZED_CONVOLUTION -for (int i = 0; i < np; i++) - sum += func[i] * m_adFilter[n - i + (np - 1)]; + for (int i = 0; i < np; i++) + sum += func[i] * m_adFilter[n - i + (np - 1)]; #else -double* f2 = m_adFilter + n + (np - 1); -for (int i = 0; i < np; i++) - sum += *func++ * *f2--; + double* f2 = m_adFilter + n + (np - 1); + for (int i = 0; i < np; i++) + sum += *func++ * *f2--; #endif - + return (sum * dx); } @@ -602,21 +705,22 @@ for (int i = 0; i < np; i++) void ProcessSignal::finiteFourierTransform (const double input[], double output[], const int n, int direction) { - complex complexOutput[n]; - - finiteFourierTransform (input, complexOutput, n, direction); - for (int i = 0; i < n; i++) - output[i] = complexOutput[i].real(); + std::complex* complexOutput = new std::complex [n]; + + finiteFourierTransform (input, complexOutput, n, direction); + for (int i = 0; i < n; i++) + output[i] = complexOutput[i].real(); + delete [] complexOutput; } void -ProcessSignal::finiteFourierTransform (const double input[], complex output[], const int n, int direction) +ProcessSignal::finiteFourierTransform (const double input[], std::complex output[], const int n, int direction) { if (direction < 0) direction = -1; else direction = 1; - + double angleIncrement = direction * 2 * PI / n; for (int i = 0; i < n; i++) { double sumReal = 0; @@ -630,25 +734,25 @@ ProcessSignal::finiteFourierTransform (const double input[], complex out sumReal /= n; sumImag /= n; } - output[i] = complex (sumReal, sumImag); + output[i] = std::complex (sumReal, sumImag); } } void -ProcessSignal::finiteFourierTransform (const complex input[], complex output[], const int n, int direction) +ProcessSignal::finiteFourierTransform (const std::complex input[], std::complex output[], const int n, int direction) { if (direction < 0) direction = -1; else direction = 1; - + double angleIncrement = direction * 2 * PI / n; for (int i = 0; i < n; i++) { - complex sum (0,0); + std::complex sum (0,0); for (int j = 0; j < n; j++) { double angle = i * j * angleIncrement; - complex exponentTerm (cos(angle), sin(angle)); + std::complex exponentTerm (cos(angle), sin(angle)); sum += input[j] * exponentTerm; } if (direction < 0) { @@ -659,16 +763,16 @@ ProcessSignal::finiteFourierTransform (const complex input[], complex input[], double output[], const int n, int direction) +ProcessSignal::finiteFourierTransform (const std::complex input[], double output[], const int n, int direction) { if (direction < 0) direction = -1; else direction = 1; - + double angleIncrement = direction * 2 * PI / n; for (int i = 0; i < n; i++) { - double sumReal = 0; + double sumReal = 0; for (int j = 0; j < n; j++) { double angle = i * j * angleIncrement; sumReal += input[j].real() * cos(angle) - input[j].imag() * sin(angle); @@ -683,84 +787,84 @@ ProcessSignal::finiteFourierTransform (const complex input[], double out // Table-based routines void -ProcessSignal::finiteFourierTransform (const double input[], complex output[], int direction) const +ProcessSignal::finiteFourierTransform (const double input[], std::complex output[], int direction) const { if (direction < 0) direction = -1; else direction = 1; - + for (int i = 0; i < m_nFilterPoints; i++) { double sumReal = 0, sumImag = 0; for (int j = 0; j < m_nFilterPoints; j++) { int tableIndex = i * j; if (direction > 0) { - sumReal += input[j] * m_adFourierCosTable[tableIndex]; - sumImag += input[j] * m_adFourierSinTable[tableIndex]; + sumReal += input[j] * m_adFourierCosTable[tableIndex]; + sumImag += input[j] * m_adFourierSinTable[tableIndex]; } else { - sumReal += input[j] * m_adFourierCosTable[tableIndex]; - sumImag -= input[j] * m_adFourierSinTable[tableIndex]; + sumReal += input[j] * m_adFourierCosTable[tableIndex]; + sumImag -= input[j] * m_adFourierSinTable[tableIndex]; } } if (direction < 0) { sumReal /= m_nFilterPoints; sumImag /= m_nFilterPoints; } - output[i] = complex (sumReal, sumImag); + output[i] = std::complex (sumReal, sumImag); } } // (a+bi) * (c + di) = (ac - bd) + (ad + bc)i void -ProcessSignal::finiteFourierTransform (const complex input[], complex output[], int direction) const +ProcessSignal::finiteFourierTransform (const std::complex input[], std::complex output[], int direction) const { if (direction < 0) direction = -1; else direction = 1; - + for (int i = 0; i < m_nFilterPoints; i++) { double sumReal = 0, sumImag = 0; for (int j = 0; j < m_nFilterPoints; j++) { int tableIndex = i * j; if (direction > 0) { - sumReal += input[j].real() * m_adFourierCosTable[tableIndex] - - input[j].imag() * m_adFourierSinTable[tableIndex]; - sumImag += input[j].real() * m_adFourierSinTable[tableIndex] - + input[j].imag() * m_adFourierCosTable[tableIndex]; + sumReal += input[j].real() * m_adFourierCosTable[tableIndex] + - input[j].imag() * m_adFourierSinTable[tableIndex]; + sumImag += input[j].real() * m_adFourierSinTable[tableIndex] + + input[j].imag() * m_adFourierCosTable[tableIndex]; } else { - sumReal += input[j].real() * m_adFourierCosTable[tableIndex] - - input[j].imag() * -m_adFourierSinTable[tableIndex]; - sumImag += input[j].real() * -m_adFourierSinTable[tableIndex] - + input[j].imag() * m_adFourierCosTable[tableIndex]; + sumReal += input[j].real() * m_adFourierCosTable[tableIndex] + - input[j].imag() * -m_adFourierSinTable[tableIndex]; + sumImag += input[j].real() * -m_adFourierSinTable[tableIndex] + + input[j].imag() * m_adFourierCosTable[tableIndex]; } } if (direction < 0) { sumReal /= m_nFilterPoints; sumImag /= m_nFilterPoints; } - output[i] = complex (sumReal, sumImag); + output[i] = std::complex (sumReal, sumImag); } } void -ProcessSignal::finiteFourierTransform (const complex input[], double output[], int direction) const +ProcessSignal::finiteFourierTransform (const std::complex input[], double output[], int direction) const { if (direction < 0) direction = -1; else direction = 1; - + for (int i = 0; i < m_nFilterPoints; i++) { - double sumReal = 0; + double sumReal = 0; for (int j = 0; j < m_nFilterPoints; j++) { int tableIndex = i * j; if (direction > 0) { - sumReal += input[j].real() * m_adFourierCosTable[tableIndex] - - input[j].imag() * m_adFourierSinTable[tableIndex]; + sumReal += input[j].real() * m_adFourierCosTable[tableIndex] + - input[j].imag() * m_adFourierSinTable[tableIndex]; } else { - sumReal += input[j].real() * m_adFourierCosTable[tableIndex] - - input[j].imag() * -m_adFourierSinTable[tableIndex]; + sumReal += input[j].real() * m_adFourierCosTable[tableIndex] + - input[j].imag() * -m_adFourierSinTable[tableIndex]; } } if (direction < 0) { @@ -770,63 +874,3 @@ ProcessSignal::finiteFourierTransform (const complex input[], double out } } -// Odd Number of Points -// Natural Frequency Order: -(n-1)/2...-1,0,1...(n-1)/2 -// Fourier Frequency Order: 0, 1..(n-1)/2,-(n-1)/2...-1 -// Even Number of Points -// Natural Frequency Order: -n/2...-1,0,1...((n/2)-1) -// Fourier Frequency Order: 0,1...((n/2)-1),-n/2...-1 - -void -ProcessSignal::shuffleNaturalToFourierOrder (double* pdVector, const int n) -{ - double* pdTemp = new double [n]; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[0] = pdVector[iHalfN]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + 1 + iHalfN]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; - } else { // Even - int iHalfN = n / 2; - pdTemp[0] = pdVector[iHalfN]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + iHalfN]; - for (int i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; - } - - for (int i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete pdTemp; -} - - -void -ProcessSignal::shuffleFourierToNaturalOrder (double* pdVector, const int n) -{ - double* pdTemp = new double [n]; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[iHalfN] = pdVector[0]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i + 1 + iHalfN] = pdVector[i + 1]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN + 1]; - } else { // Even - int iHalfN = n / 2; - pdTemp[iHalfN] = pdVector[0]; - for (int i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN]; - for (int i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i+1]; - } - - for (int i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete pdTemp; -} -