Go to the documentation of this file.00001 #include "ForIA/AnalysisTools/Wavelet.hh"
00002
00003 #include "boost/lexical_cast.hpp"
00004
00005 #include <cmath>
00006
00007 #include <stdexcept>
00008
00009
00010 namespace ForIA{
00012 Wavelet::Wavelet(): m_doInitialise(true), m_haveSetRangeStart(false), m_haveSetRangeEnd(false),
00013 m_nSubSamples(0), m_wavelet(0), m_workspace(0){
00014
00015 }
00016
00018 Wavelet::~Wavelet(){
00019 if(m_workspace) gsl_wavelet_workspace_free(m_workspace);
00020 if(m_wavelet) gsl_wavelet_free(m_wavelet);
00021 }
00022
00024 void Wavelet::initialise(){
00025
00026 m_nSegments = m_grid.size();
00027
00028 if(!m_haveSetRangeStart || !m_haveSetRangeEnd){
00029 throw std::runtime_error("Wavelet: Cannot initialise without first setting co-ordinate range of input sequence");
00030 }
00031
00032 if( ((m_nSegments-1) & m_nSegments)){
00033 throw std::runtime_error("Number of segments must be radix 2. Number given is " +
00034 boost::lexical_cast<std::string>(m_nSegments));
00035 return;
00036 }
00037
00038 m_range = m_max - m_min;
00039
00040 m_freqMax = 0.5 * (double)m_nSegments / m_range;
00041
00042 m_freqMin = 0.5 / m_range;
00043
00044 m_nSubSamples = 0;
00045
00046 int tmp = m_nSegments;
00047
00048 while(tmp >>= 1) ++m_nSubSamples;
00049
00050
00051
00052 m_workspace = gsl_wavelet_workspace_alloc(m_nSegments);
00053
00054 m_wavelet = gsl_wavelet_alloc(gsl_wavelet_daubechies_centered, 4);
00055
00056 m_bands.clear();
00057
00058 unsigned int kMax=1;
00059
00060 unsigned int index=1;
00061
00062 double freqMin = m_freqMin;
00063 double freqMax = freqMin * 2.;
00064
00065 unsigned int scale = m_nSegments;
00066
00067 double physScale = m_range;
00068
00069 for(unsigned int j=0; j!= nSubBands(); ++j){
00070
00071 m_bands.push_back(FrequencyBand());
00072
00073 m_bands.back().m_parent = this;
00074 m_bands.back().m_level = nSubBands() - j;
00075 m_bands.back().m_lowerFreq = freqMin;
00076 m_bands.back().m_upperFreq = freqMax;
00077 m_bands.back().m_physScale = physScale;
00078
00079 m_bands.back().m_scale = scale;
00080
00081 double tau_min = m_min;
00082 double tau_incr = m_range / (double)kMax;
00083 double tau_max = tau_min + tau_incr;
00084
00085 for(unsigned int k=0; k != kMax; ++k){
00086
00087 m_bands.back().m_coefficients.push_back(Coefficient());
00088 m_bands.back().m_coefficients.back().m_arrayPosition=index;
00089 m_bands.back().m_coefficients.back().m_level = m_bands.back().level();
00090 m_bands.back().m_coefficients.back().m_index = k;
00091 m_bands.back().m_coefficients.back().m_upper = tau_max;
00092 m_bands.back().m_coefficients.back().m_lower = tau_min;
00093
00094 m_bands.back().m_coefficients.back().m_scale = scale;
00095
00096 tau_min = tau_max;
00097 tau_max += tau_incr;
00098
00099 ++index;
00100 }
00101
00102 freqMin = freqMax;
00103 freqMax *= 2.;
00104 kMax *= 2;
00105 scale /= 2;
00106 physScale *= 0.5;
00107 }
00108
00109 m_doInitialise = false;
00110
00111 return;
00112 }
00113
00115 void Wavelet::setRangeStart(double min){
00116 if(!m_doInitialise){
00117 throw std::runtime_error("Wavelet: Cannot set start range of co-ordinate after initialisation!");
00118 }
00119
00120 m_min = min;
00121
00122 m_haveSetRangeStart = true;
00123 return;
00124 }
00125
00127 void Wavelet::setRangeEnd(double max){
00128 if(!m_doInitialise){
00129 throw std::runtime_error("Wavelet: Cannot set end range of co-ordinate after initialisation!");
00130 }
00131
00132 m_max = max;
00133
00134 m_haveSetRangeEnd = true;
00135 return;
00136 }
00137
00139 unsigned int Wavelet::nSubBands()const{
00140 return m_nSubSamples;
00141 }
00142
00144 const Wavelet::FrequencyBand &Wavelet::frequencyBand(unsigned int level)const{
00145 unsigned int index = nSubBands() - level;
00146 return m_bands[index];
00147 }
00148
00150 const Wavelet::Coefficient &Wavelet::coefficient(unsigned int level, unsigned int index)const{
00151 return frequencyBand(level).coefficient(index);
00152 }
00153
00155 void Wavelet::setGrid(const vector<double> &grid){
00156
00157 m_grid = grid;
00158
00159 if(m_doInitialise) initialise();
00160
00161 if(m_grid.size() != m_nSegments){
00162 throw std::runtime_error("Number of segments has changed since initialisation! Was first called with " +
00163 boost::lexical_cast<std::string>(m_nSegments) +
00164 " segments, now being called with " + boost::lexical_cast<std::string>(m_grid.size()));
00165 }
00166
00167 vector<double> output(grid.begin(), grid.end());
00168
00169 int status = gsl_wavelet_transform_forward(m_wavelet, &(output[0]), 1, m_nSegments, m_workspace);
00170
00171 if(status != GSL_SUCCESS){
00172 throw std::runtime_error("Wavelet transform failed due to either lack of memory or data that is not radix 2!");
00173 }
00174
00175 m_smoothing = output[0];
00176
00177 unsigned int index=1;
00178
00179 for(vector<FrequencyBand>::iterator band = m_bands.begin();
00180 band != m_bands.end(); ++band){
00181
00182 band->m_doEnergy = true;
00183 band->m_doVar = true;
00184 band->m_doAv = true;
00185 for(vector<Coefficient>::iterator coeff = band->m_coefficients.begin();
00186 coeff != band->m_coefficients.end(); ++coeff){
00187
00188 coeff->m_magnitude = output[index];
00189
00190 ++index;
00191 }
00192
00193 }
00194
00195 return;
00196 }
00197
00199 void Wavelet::invert(vector<double> &sequence)const{
00200
00201 if(sequence.size() != m_nSegments){
00202 throw std::runtime_error("Number of segments in sequence to be inverted (" +
00203 boost::lexical_cast<string>(sequence.size()) + ") does not match wavelet (" +
00204 boost::lexical_cast<string>(m_nSegments) + ")");
00205 }
00206
00207 gsl_wavelet_transform_inverse(m_wavelet, &(sequence[0]), 1, m_nSegments, m_workspace);
00208
00209 return;
00210 }
00211
00213 MessageBox &operator << (MessageBox &box, const Wavelet::FrequencyBand &freq){
00214 box.setTitle("Wavelet Frequency Band");
00215
00216 box.addEntry("Level", freq.level());
00217 box.addEntry("Scale factor", freq.scale());
00218 box.addEntry("Physical scale", freq.physicalScale());
00219 box.addEntry("Number of Coefficients", freq.nCoefficients());
00220 box.addEntry("Frequency range", "{ " + boost::lexical_cast<string>(freq.lower_frequency()) + ", " +
00221 boost::lexical_cast<string>(freq.upper_frequency()) + "}");
00222
00223 return box;
00224 }
00225
00227 std::ostream &operator << (std::ostream &out, const Wavelet::FrequencyBand &freq){
00228 MessageBox tmp;
00229
00230 tmp<<freq;
00231 out<<tmp;
00232
00233 return out;
00234 }
00235
00236 }
00237
00238