CFEL - ASG Software Suite  2.5.0
CASS
fft.cpp
Go to the documentation of this file.
1 //Copyright (C) 2013 Lutz Foucar
2 //Copyright (C) 2013 Stephan Kassemeyer
3 
4 /**
5  * @file fft.cpp containing the class to calculate the fast fourier transform
6  *
7  * @author Lutz Foucar
8  */
9 
10 #include <algorithm>
11 #include <functional>
12 #include <numeric>
13 
14 #include "fft.h"
15 #include "result.hpp"
16 #include "cass_event.h"
17 #include "cass_settings.h"
18 #include "log.h"
19 #include "processor.h"
20 
21 using namespace cass;
22 using namespace std;
23 using tr1::bind;
24 using tr1::placeholders::_1;
25 using tr1::placeholders::_2;
26 
27 
28 pp312::pp312(const name_t &name)
29  : Processor(name)
30 {
31  loadSettings(0);
32 }
33 
34 // todo:
35 // fftw_destroy_plan(plan);
36 
37 void pp312::loadSettings(size_t)
38 {
39  CASSSettings s;
40  s.beginGroup("Processor");
42 
43  setupGeneral();
44  _hist = setupDependency("InputName");
45  bool ret (setupCondition());
46  if (!(ret && _hist))
47  return;
48 
49  const int dim(_hist->result().dim());
50  if (dim == 1)
51  {
52  _Nx = _hist->result().shape().first;
53  _func = std::tr1::bind(&pp312::fft1d,this,_1,_2);
54  _fft_tmp_padding = (_Nx&1) ? 1 : 2;
55  vector<double> fft_tmp;
56  fft_tmp.resize(_Nx+_fft_tmp_padding);
57  double* tmpdata(&(fft_tmp.front()));
58  _fftw_plan = fftw_plan_dft_r2c_1d(_Nx, tmpdata, reinterpret_cast<fftw_complex*>(tmpdata), FFTW_MEASURE);
59  }
60  else if (dim == 2)
61  {
62  _Nx = _hist->result().shape().first;
63  _Ny = _hist->result().shape().second;
64  _func = std::tr1::bind(&pp312::fft2d,this,_1,_2);
65  _fft_tmp_padding = (_Nx&1) ? 1 : 2;
66  vector<double> fft_tmp;
67  fft_tmp.resize(_Ny*(_Nx+_fft_tmp_padding));
68  double* tmpdata(&(fft_tmp.front()));
69  _fftw_plan = fftw_plan_dft_r2c_2d(_Ny, _Nx, tmpdata, reinterpret_cast<fftw_complex*>(tmpdata), FFTW_MEASURE);
70  }
71  else
72  throw invalid_argument("pp312::loadSettings(): Input Histogram '" + _hist->name() +
73  "' has unsupported dimenstion '" + toString(dim) + "'");
74 
75  createHistList(_hist->result().clone());
76 
77  Log::add(Log::INFO,"Processor '" + name() +
78  "' will calculate the fft of '" + _hist->name() +
79  "'. Condition is '" + _condition->name() + "'");
80 }
81 
83 {
84  // if fftw was to support arbitrary precision, traits could be used to determine the precision of
85  // a given Histogram and it could be cast to fftw types as follows:
86  // fftw_plan plan = fftw_plan_dft_r2c_1d(_Nx, in, reinterpret_cast<pp312Traits<HistogramFloatBase::value_t>::fftw_complex_type*> (out), FFTW_MEASURE);
87  // unfortunately though, fftw only supports one type of precision determined during compilation.
88  // so we have to convert to double, the standard precision.
89  std::vector<double> fft_tmp;
90  fft_tmp.resize(_Nx+_fft_tmp_padding);
91  copy(in, in+_Nx, fft_tmp.begin());
92  double* tmpdata(&(fft_tmp.front()));
93 
94  fftw_execute_dft_r2c( _fftw_plan, tmpdata, reinterpret_cast<fftw_complex*>(tmpdata));
95 
96  // fftw saves some memory for real-valued input data.
97  // we have to restore the full data by unpacking hermitian symmetry pairs:
98 
99  // shift first half:
100  for (size_t xx=0;xx<_Nx/2;++xx)
101  {
102  result_t::value_t v_real = tmpdata[xx*2];
103  result_t::value_t v_imag = tmpdata[xx*2+1];
104  out[xx+_Nx/2] = v_real*v_real + v_imag*v_imag;
105  }
106  // shift second half:
107  for (size_t xx=_Nx/2;xx<_Nx;++xx)
108  {
109  result_t::value_t v_real = tmpdata[xx*2];
110  result_t::value_t v_imag = tmpdata[xx*2+1];
111  out[xx-_Nx/2] = v_real*v_real + v_imag*v_imag;
112  }
113 }
114 
116 {
117  // if fftw was to support arbitrary precision, traits could be used to determine the precision of
118  // a given Histogram and it could be cast to fftw types as follows:
119  // fftw_plan plan = fftw_plan_dft_r2c_2d(_Nx, _Ny, in, reinterpret_cast<pp312Traits<HistogramFloatBase::value_t>::fftw_complex_type*> (out), FFTW_MEASURE);
120  // unfortunately though, fftw only supports one type of precision determined during compilation.
121  // so we have to convert to double, the standard precision.
122 
123 
124  vector<double> fft_tmp;
125  fft_tmp.resize(_Ny*(_Nx+_fft_tmp_padding));
126  double* tmpdata(&(fft_tmp.front()));
127  //std::copy(in, in+_Nx*_Ny, fft_tmp.begin());
128  for (size_t yy=0;yy<_Ny;++yy)
129  for (size_t xx=0;xx<_Nx;++xx)
130  tmpdata[yy*(_Nx+_fft_tmp_padding)+xx]=in[yy*_Nx+xx];
131 
132 // for (int yy=0;yy<_Ny;++yy)
133 // for (int xx=0;xx<_Nx;++xx)
134 // tmpdata[yy*(_Nx+_fft_tmp_padding)+xx]=0;
135 // for (int yy=_Ny/2-30;yy<_Ny/2+30;++yy)
136 // for (int xx=_Nx/2-30;xx<_Nx/2+30;++xx)
137 // tmpdata[yy*(_Nx+_fft_tmp_padding)+xx]=10;
138 
139 
140  fftw_execute_dft_r2c( _fftw_plan, tmpdata, reinterpret_cast<fftw_complex*>(tmpdata));
141 
142  // fftw saves some memory for real-valued input data.
143  // we have to restore the full data by unpacking hermitian symmetry pairs:
144  for (size_t xx=0;xx<_Nx/2;++xx)
145  for (size_t yy=0;yy<_Ny/2;++yy)
146  out[_Ny*xx+yy]=0;
147  for (size_t ii=0;ii<_Nx/2*_Ny/2;++ii)
148  out[ii]=tmpdata[ii*2];
149 
150  // shift first quadrant:
151  for (size_t xx=_Nx/2;xx<_Nx;++xx)
152  {
153  for (size_t yy=_Ny/2;yy<_Ny;++yy)
154  {
155  result_t::value_t v_real = tmpdata[(yy-_Ny/2)*(_Nx+_fft_tmp_padding)+(xx-_Nx/2)*2];
156  result_t::value_t v_imag = tmpdata[(yy-_Ny/2)*(_Nx+_fft_tmp_padding)+(xx-_Nx/2)*2+1];
157  out[_Nx*(yy)+xx] = v_real*v_real + v_imag*v_imag;
158  }
159  }
160  // shift second quadrant:
161  for (size_t xx=_Nx/2;xx<_Nx;++xx)
162  {
163  for (size_t yy=0;yy<_Ny/2;++yy)
164  {
165  result_t::value_t v_real = tmpdata[(yy+_Ny/2)*(_Nx+_fft_tmp_padding)+(xx-_Nx/2)*2];
166  result_t::value_t v_imag = tmpdata[(yy+_Ny/2)*(_Nx+_fft_tmp_padding)+(xx-_Nx/2)*2+1];
167  out[_Nx*(yy)+xx] = v_real*v_real + v_imag*v_imag;
168  }
169  }
170  // fill in hermitian symmetry:
171  for (size_t xx=0;xx<_Nx/2;++xx)
172  {
173  for (size_t yy=0;yy<_Ny;++yy)
174  {
175  out[_Nx*(yy)+xx] = out[ _Nx*(_Ny-yy) + _Nx-xx ];
176  }
177  }
178  // special treatment for (0,0):
179  out[_Nx/2*_Ny+_Ny/2] = tmpdata[0]*tmpdata[0] + tmpdata[1]*tmpdata[1];
180 }
181 
182 void pp312::process(const CASSEvent &evt, result_t &result)
183 {
184  const result_t& hist(_hist->result(evt.id()));
185  QReadLocker lock(&hist.lock);
186 
187  _func(hist.begin(),result.begin());
188 }
189 
storage_t::const_iterator const_iterator
a const iterator on the storage
Definition: result.hpp:338
Event to store all LCLS Data.
Definition: cass_event.h:32
virtual void createHistList(result_t::shared_pointer result)
create result list.
Definition: processor.cpp:79
fftw_plan _fftw_plan
fftw plan - stores fftw optimization data for given data type+size
Definition: fft.h:106
size_t _Ny
Definition: fft.h:102
const name_t name() const
retrieve the name of this processor
Definition: processor.h:167
file contains declaration of the CASSEvent
float value_t
the values of this container
Definition: result.hpp:326
Settings for CASS.
Definition: cass_settings.h:30
virtual void process(const CASSEvent &evt, result_t &result)
process the event
Definition: fft.cpp:182
STL namespace.
result classes
int _fft_tmp_padding
info about temporary memory for the fftw calculation
Definition: fft.h:109
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
const_iterator begin() const
retrieve a iterator for read access to beginning
Definition: result.hpp:608
fromStdString(const std::string &str)
shared_pointer _hist
pp containing histogram to calculate the autocorrelation for
Definition: fft.h:98
base class for processors.
Definition: processor.h:39
void fft2d(result_t::const_iterator in, result_t::iterator out)
calculate the absolute square fft for 2d data
Definition: fft.cpp:115
pp312(const name_t &name)
constructor
Definition: fft.cpp:28
shared_pointer setupDependency(const std::string &depVarName, const name_t &name="")
setup the dependecy.
Definition: processor.cpp:114
std::tr1::function< void(result_t::const_iterator, result_t::iterator)> _func
function to call for processing
Definition: fft.h:112
QReadWriteLock lock
lock for locking operations on the data of the container
Definition: result.hpp:954
virtual void loadSettings(size_t)
load the settings of this pp
Definition: fft.cpp:37
id_t & id()
setters
Definition: cass_event.h:64
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
file contains processors baseclass declaration
storage_t::iterator iterator
a iterator on the storage
Definition: result.hpp:335
void setupGeneral()
general setup of the processor
Definition: processor.cpp:85
file contains specialized class that do the settings for cass
void fft1d(result_t::const_iterator in, result_t::iterator out)
calculate the absolute square fft for 1d data
Definition: fft.cpp:82
shared_pointer _condition
pointer to the processor that will contain the condition
Definition: processor.h:277
containing the class to calculate the fast fourier transform
bool setupCondition(bool defaultConditionType=true)
setup the condition.
Definition: processor.cpp:94
std::string name_t
define the name type
Definition: processor.h:46
contains a logger for cass
beginGroup(const QString &prefix)
size_t _Nx
the shape of the incomming histogram
Definition: fft.h:101