AdcDeconvoluteFFT_tool.cc
Go to the documentation of this file.
1 // AdcDeconvoluteFFT_tool.cc
2 
3 #include "AdcDeconvoluteFFT.h"
6 #include "TMath.h"
7 #include "TDecompLU.h"
8 #include "TDecompSVD.h"
9 #include <iostream>
10 #include <iomanip>
11 
12 using std::string;
13 using std::cout;
14 using std::endl;
15 using std::setw;
16 using std::fixed;
17 using std::setprecision;
18 
19 using Index = unsigned int;
21 using DoubleVector = std::vector<double>;
22 using Name = std::string;
23 using DFT = DuneFFT::DFT;
24 
25 //**********************************************************************
26 // Local functions.
27 //**********************************************************************
28 
29 namespace {
30 
31 // Fill a matrix with a vector.
32 // The matrix is near diagonal with the near-diagonal columns populated with
33 // the entries in the vector vrcol.
34 // The diagonal element is vres[ishift].
35 //
36 // vec - Input smearing vector.
37 // ishift - vector offset in matrix
38 // mres - Output matrix.
39 // smsgpre - If not blank, a message prefixed with this string is logged for each row.
40 template<class RootMatrix>
41 int responseVectorToMatrix(const DoubleVector& vrcol, Index ishiftin, RootMatrix& mres,
42  int logLevel, string smsgpre ="") {
43  string myname = smsgpre + "reponseVectorToMatrix: ";
44  // Flip vector so we can fill rows instead of columns.
45  Index nvec = vrcol.size();
46  Index nrow = mres.GetNrows();
47  Index ncol = mres.GetNcols();
48  if ( nvec == 0 ) {
49  if ( logLevel > 0 ) cout << myname << "WARNING: Response vector is empty." << endl;
50  return 1;
51  }
52  if ( ishiftin >= nvec ) {
53  if ( logLevel > 0 ) cout << myname << "WARNING: Shift " << ishiftin
54  << " is outside vector range (0, " << nvec << "]" << endl;
55  return 2;
56  }
57  if ( logLevel >= 4 ) {
58  cout << myname << "Matrix is " << nrow << " x " << ncol << endl;
59  cout << myname << "Vector has length " << nvec << " and shift " << ishiftin << endl;
60  }
61  Index ishift = nvec - 1 - ishiftin;
62  DoubleVector vrrow(nvec, 0.0);
63  for ( Index ircol=0, irrow=nvec-1; ircol<nvec; ++ircol, --irrow ) {
64  vrrow[irrow] = vrcol[ircol];
65  }
66  // Populate matrix with vector.
67  if ( nvec == 0 ) return 0;
68  for ( Index irow=0; irow<ncol; ++irow ) {
69  Index icol = irow > ishift ? irow - ishift : 0;
70  Index ivec = icol + ishift - irow;
71  Index nvecInsert = icol + nvec < nrow ? nvec - ivec : nrow - icol;
72  if ( logLevel >= 4 ) {
73  cout << smsgpre << "Column " << icol << ": inserting " << nvecInsert
74  << " entries at row " << irow << endl;
75  }
76  mres.InsertRow(irow, icol, &vrrow[ivec], nvecInsert);
77  }
78  return 0;
79 }
80 
81 template<class RootMatrix>
82 int responseVectorToMatrix(const FloatVector& vresf, Index ishift, RootMatrix& mres,
83  int logLevel, string smsgpre ="") {
84  DoubleVector vresd(vresf.begin(), vresf.end());
85  return responseVectorToMatrix(vresd, ishift, mres, logLevel, smsgpre);
86 }
87 
88 } // End unnamed namepsace.
89 
90 //**********************************************************************
91 // Class methods.
92 //**********************************************************************
93 
95 : m_LogLevel(ps.get<int>("LogLevel")),
96  m_Action(ps.get<Index>("Action")),
97  m_ResponseVectors(ps.get<ResponseVectorVector>("ResponseVectors")),
98  m_ResponseCenters(ps.get<IndexVector>("ResponseCenters")),
99  m_SmoothVectors(ps.get<ResponseVectorVector>("SmoothVectors")),
100  m_SmoothScales(ps.get<FloatVector>("SmoothScales")),
101  m_GausFilterSigmas(ps.get<FloatVector>("GausFilterSigmas")),
102  m_LowFilterWidths(ps.get<FloatVector>("LowFilterWidths")),
103  m_LowFilterPowers(ps.get<FloatVector>("LowFilterPowers")),
104  m_IndexMapTool(ps.get<Name>("IndexMapTool")),
105  m_useResponse(false), m_useFilter(false),
106  m_doFFTConvolute(false), m_doDirectConvolute(false),
107  m_doDeconvolute(false), m_directDeconvolute(0) {
108  const Name myname = "AdcDeconvoluteFFT:ctor: ";
109  // Set the action flags.
110  Name amsg;
111  if ( m_Action == 0 ) {
112  amsg = "No action.";
113  } else if ( m_Action == 1 ) {
114  m_doDeconvolute = true;
115  m_useResponse = true;
116  m_useFilter = true;
117  amsg = "Deconvolution.";
118  } else if ( m_Action == 2 ) {
119  m_doFFTConvolute = true;
120  m_useResponse = true;
121  amsg = "FFT response convolution.";
122  } else if ( m_Action == 3 ) {
123  m_doFFTConvolute = true;
124  m_useFilter = true;
125  amsg = "FFT filter convolution.";
126  } else if ( m_Action == 4 ) {
127  m_doDirectConvolute = true;
128  m_useResponse = true;
129  amsg = "Direct response convolution.";
130  } else if ( m_Action == 5 ) {
131  m_doDirectConvolute = true;
132  m_useFilter = true;
133  amsg = "Direct filter convolution.";
134  } else if ( m_Action == 6 ) {
136  amsg = "Direct matrix deconvolution.";
137  } else if ( m_Action == 7 ) {
139  amsg = "Filtered matrix deconvolution.";
140  } else if ( m_Action == 8 ) {
142  amsg = "Chi-square matrix deconvolution.";
143  } else if ( m_Action == 9 ) {
145  amsg = "Direct deconvolution.";
146  } else {
147  cout << myname << "ERROR: Invalid action flag: " << m_Action << endl;
148  }
149  // Fetch index mapper.
150  if ( m_IndexMapTool.size() ) {
153  if ( m_channelToIndex ) {
154  cout << myname << "Using channel mapping tool " << m_IndexMapTool << endl;
155  } else {
156  cout << myname << "WARNING: Channel mapping tool not found: " << m_IndexMapTool << endl;
157  }
158  }
159  if ( m_LogLevel >= 1 ) {
160  std::ios cout_state(nullptr);
161  cout_state.copyfmt(std::cout);
162  cout << myname << "Parameters:" << endl;
163  cout << myname << " LogLevel: " << m_LogLevel << endl;
164  cout << myname << " Action: " << m_Action << " (" << amsg << ")" << endl;
165  cout << myname << " ResponseVectors: [";
166  Index indent = 22;
167  bool first = true;
168  for ( const ResponseVector& vec : m_ResponseVectors ) {
169  if ( first ) first = false;
170  else cout << ", ";
171  for ( Index isam=0; isam<vec.size(); ++isam ) {
172  float val = vec[isam];
173  if ( isam != 0 ) cout << ", ";
174  if ( isam == 0 ) cout << "\n" << myname << setw(indent) << "[";
175  else if ( 10*(isam/10) == isam ) cout << "\n" << myname << setw(indent) << " ";
176  cout << setw(11) << fixed << setprecision(7) << val;
177  }
178  cout << "]";
179  }
180  cout << endl;
181  cout << myname << setw(indent-2) << "]" << endl;
182  cout << myname << " ResponseShifts: [";
183  first = true;
184  for ( Index val : m_ResponseCenters ) {
185  if ( first ) first = false;
186  else cout << ", ";
187  cout << val;
188  }
189  cout << "]" << endl;
190  cout << myname << " SmoothVectors: [";
191  indent = 22;
192  first = true;
193  for ( const ResponseVector& vec : m_SmoothVectors ) {
194  if ( first ) first = false;
195  else cout << ", ";
196  for ( Index isam=0; isam<vec.size(); ++isam ) {
197  float val = vec[isam];
198  if ( isam != 0 ) cout << ", ";
199  if ( isam == 0 ) cout << "\n" << myname << setw(indent) << "[";
200  else if ( 10*(isam/10) == isam ) cout << "\n" << myname << setw(indent) << " ";
201  cout << setw(11) << fixed << setprecision(7) << val;
202  }
203  cout << "]";
204  }
205  cout << endl;
206  cout << myname << setw(indent-2) << "]" << endl;
207  cout << myname << " SmoothScales: [";
208  first = true;
209  for ( float val : m_SmoothScales ) {
210  if ( first ) first = false;
211  else cout << ", ";
212  cout << setw(11) << fixed << setprecision(7) << val;
213  }
214  cout << "]" << endl;
215  cout << myname << " GausFilterSigmas: [";
216  first = true;
217  for ( float sgm : m_GausFilterSigmas ) {
218  if ( first ) first = false;
219  else cout << ", ";
220  cout << sgm;
221  }
222  cout << "]" << endl;
223  cout << myname << " LowFilterWidths: [";
224  first = true;
225  for ( float val : m_LowFilterWidths ) {
226  if ( first ) first = false;
227  else cout << ", ";
228  cout << val;
229  }
230  cout << "]" << endl;
231  cout << myname << " LowFilterPowers: [";
232  first = true;
233  for ( float val : m_LowFilterPowers ) {
234  if ( first ) first = false;
235  else cout << ", ";
236  cout << val;
237  }
238  cout << "]" << endl;
239  cout << myname << " ChannelMapTool: " << m_IndexMapTool << endl;;
240  std::cout.copyfmt(cout_state);
241  }
242 }
243 
244 //**********************************************************************
245 
247  const string myname = "AdcDeconvoluteFFT::update: ";
248  DataMap ret;
249  Index icha = acd.channel();
250  if ( m_LogLevel >= 2 ) cout << myname << "Processing run " << acd.run() << " event " << acd.event()
251  << " channel " << icha << endl;
252  // Retrieve the response vector and sigma.
253  Index ivec = 0;
254  if ( m_channelToIndex ) {
255  ivec = m_channelToIndex->get(icha);
256  }
257  if ( ivec >= m_ResponseVectors.size() ) {
258  cout << "WARNING: There is no response vector for index " << ivec
259  << " (channel " << icha << ")." << endl;
260  return ret;
261  }
262  const ResponseVector& responseVector = m_ResponseVectors[ivec];
263  Index ishift = ivec < m_ResponseCenters.size() ? m_ResponseCenters[ivec] : 0;
264  if ( ivec >= m_GausFilterSigmas.size() ) {
265  cout << "WARNING: There is no Gaus filter sigma for index "
266  << ivec << " (channel " << icha << ")." << endl;
267  return ret;
268  }
269  const ResponseVector empty;
270  const ResponseVector& smoothVector = ivec < m_SmoothVectors.size() ? m_SmoothVectors[ivec] : empty;
271  float smoothScale = ivec < m_SmoothScales.size() ? m_SmoothScales[ivec] : 1.0;
272  float gausFilterSigma = m_GausFilterSigmas[ivec];
273  float lfwidth = -1.0;
274  float lfpower = 0;
275  if ( ivec >= m_LowFilterWidths.size() ) {
276  cout << "WARNING: There is no low-filter width for index "
277  << ivec << " (channel " << icha << ")." << endl;
278  } else {
279  lfwidth = m_LowFilterWidths[ivec];
280  if ( lfwidth > 0.0 && ivec >= m_LowFilterPowers.size() ) {
281  cout << "WARNING: There is no low-filter width for index "
282  << ivec << " (channel " << icha << ")." << endl;
283  return ret;
284  }
285  lfpower = m_LowFilterPowers[ivec];
286  }
287  // Do action.
290  Index rstat = 0;
291  Index fftLogLevel = m_LogLevel > 2 ? m_LogLevel - 2 : 0.0;
292 
294 
295  bool useFFT = m_doDeconvolute || m_doFFTConvolute;
296 
297  // Input data.
298  FloatVector& xdasInp = acd.samples;
299  Index nsam = xdasInp.size();
300  if ( nsam == 0 ) return ret;
301 
302  // Build the response sequence extended to the data length.
303  FloatVector xdasRes(nsam, 0.0);
304  Index nres = responseVector.size();
305  if ( m_useResponse ) {
306  if ( m_LogLevel >= 3 ) cout << myname << "Building time-domain response vector." << endl;
307  if ( nres == 0 ) {
308  cout << myname << "ERROR: Response function is undefined." << endl;
309  return ret.setStatus(1);
310  }
311  if ( nsam < nres ) {
312  cout << myname << "WARNING: Data is shorter than the response function. No action taken." << endl;
313  return ret.setStatus(2);
314  }
315  for ( Index isam=0; isam<nres; ++isam ) {
316  Index jsam = isam >= ishift ? isam - ishift : nsam + isam - ishift;
317  xdasRes[jsam] = responseVector[isam];
318  }
319  }
320 
321  // Build response deconvolution.
322  // Transform the response.
323  // We may want to cache this result mapped by nsam.
324  DFT dftRes(fnormConv);
325  if ( m_useResponse && useFFT ) {
326  if ( m_LogLevel >= 3 ) cout << myname << "Using FFT to build frequency-domain response vectors." << endl;
327  rstat = DuneFFT::fftForward(xdasRes, dftRes, fftLogLevel);
328  if ( rstat ) {
329  cout << myname << "WARNING: Unable to xform response function. No action taken." << endl;
330  return ret.setStatus(3);
331  }
332  if ( m_LogLevel >= 4 ) {
333  cout << myname << "Frequency components:" << endl;
334  for ( Index ifrq=0; ifrq<dftRes.nCompact(); ++ifrq ) {
335  cout << myname << setw(4) << ifrq << ": " << setw(10) << fixed << dftRes.amplitude(ifrq);
336  if ( ifrq < dftRes.nPhase() ) cout << " @ " << setw(10) << fixed << dftRes.phase(ifrq);
337  cout << endl;
338  }
339  }
340  }
341 
342  // Transform the data to frequency domain.
343  DFT dftInp(fnormData);
344  FloatVector xamsInp, xphsInp;
345  if ( useFFT ) {
346  if ( m_LogLevel >= 3 ) cout << myname << "Using FFT to build frequency-domain input vectors." << endl;
347  FloatVector xresInp, ximsInp;
348  rstat = DuneFFT::fftForward(xdasInp, dftInp, fftLogLevel);
349  if ( rstat ) {
350  cout << myname << "WARNING: Unable to xform input data. No action taken." << endl;
351  return ret.setStatus(4);
352  }
353  if ( m_LogLevel >= 4 ) {
354  cout << myname << "Frequency components:" << endl;
355  for ( Index ifrq=0; ifrq<dftRes.nCompact(); ++ifrq ) {
356  cout << myname << setw(4) << ifrq << ": " << setw(10) << fixed << dftInp.amplitude(ifrq);
357  if ( ifrq < dftRes.nPhase() ) cout << " @ " << setw(10) << fixed << dftInp.phase(ifrq);
358  cout << endl;
359  }
360  }
361  }
362  Index namp = dftInp.nAmplitude();
363  Index npha = dftInp.nPhase();
364 
365  // Build the filter.
366  // In frequncy space, this is just a Gaussian with sigma = N/(2*pi*sigma_t)
367  const float xmin = 1.e-20;
368  FloatVector xdasFil(nsam, 1.0);
369  DFT dftFil(fnormConv);
370  if ( m_useFilter ) {
371  FloatVector xamsFil(namp, 1.0);
372  FloatVector xphsFil(npha, 0.0);
373  if ( m_LogLevel >= 3 ) cout << myname << "Building frequency-domain filter vectors." << endl;
374  if ( gausFilterSigma > 0.0 ) {
375  static float novertwopi = 0.5*nsam/acos(-1);
376  float sigmaFreq = novertwopi/gausFilterSigma;
377  for ( Index ifrq=0; ifrq<xamsFil.size(); ++ifrq ) {
378  float val = TMath::Gaus(ifrq, 0.0, sigmaFreq, false);
379  xamsFil[ifrq] = val;
380  }
381  }
382  if ( lfwidth == 0.0 ) xamsFil[0] = 0.0;
383  if ( lfwidth > 0.0 ) {
384  double fac = lfwidth/nsam;
385  bool square = lfpower == 2.0;
386  for ( Index ifrq=0; ifrq<xamsFil.size(); ++ifrq ) {
387  double term = fac*ifrq;
388  double termp = square ? term*term : std::pow(term, lfpower);
389  double fac = termp/(1 + termp);
390  xamsFil[ifrq] *= fac;
391  }
392  }
393  dftFil.moveIn(xamsFil, xphsFil);
394  if ( m_LogLevel >= 4 ) {
395  cout << myname << "Filter frequency components:" << endl;
396  for ( Index ifrq=0; ifrq<dftFil.nCompact(); ++ifrq ) {
397  cout << myname << setw(4) << ifrq << ": " << setw(10) << fixed << dftFil.amplitude(ifrq);
398  if ( ifrq < dftFil.nPhase() ) cout << " @ " << setw(10) << fixed << dftFil.phase(ifrq);
399  cout << endl;
400  }
401  }
402  }
403 
404  // Create the output vectors.
405  FloatVector xdasOut;
406  FloatVector xamsOut, xphsOut;
407 
408  // Deconvolute/convolute (divide/multiply) in frequency space.
409  if ( useFFT ) {
410  xamsOut.resize(namp, 0.0);
411  xphsOut.resize(npha, 0.0);
412  if ( m_LogLevel >= 3 ) cout << myname << "Building frequency-domain output vectors." << endl;
413  DFT dftOut(fnormData, nsam);
414  for ( Index ifrq=0; ifrq<namp; ++ifrq ) {
415  float xamOut = dftInp.amplitude(ifrq);
416  float xphOut = dftInp.phase(ifrq);
417  if ( m_doFFTConvolute ) {
418  if ( m_useFilter ) {
419  xamOut *= dftFil.amplitude(ifrq);
420  xphOut += dftFil.phase(ifrq);
421  } else if ( m_useResponse ) {
422  xamOut *= dftRes.amplitude(ifrq);
423  xphOut += dftRes.phase(ifrq);
424  }
425  } else if ( m_doDeconvolute ) {
426  if ( m_useFilter ) {
427  xamOut *= dftFil.amplitude(ifrq);
428  xphOut += dftFil.phase(ifrq);
429  }
430  if ( xamOut > xmin ) {
431  float den = dftRes.amplitude(ifrq);
432  if ( fabs(den) < xmin ) {
433  cout << myname << "WARNING: Ignoring near-zero division in deconvolution. " << endl;
434  } else {
435  xamOut /= den;
436  }
437  xphOut -= dftRes.phase(ifrq);
438  }
439  } else {
440  cout << myname << "ERROR: Unxpected error in FFT (de)convolution." << endl;
441  }
442  if ( m_LogLevel >= 4 ) {
443  cout << myname << setw(4) << ifrq << ": " << setw(10) << fixed << xamOut;
444  if ( ifrq < npha ) cout << " @ " << setw(10) << fixed << xphOut;
445  cout << endl;
446  }
447  dftOut.setAmplitude(ifrq, xamOut);
448  xamsOut[ifrq] = xamOut;
449  if ( ifrq < npha ) {
450  dftOut.setPhase(ifrq, xphOut);
451  xphsOut[ifrq] = xphOut;
452  }
453  }
454 
455  // Transform back.
456  if ( m_LogLevel >= 3 ) cout << myname << "Using FFT to build time-domain output vector." << endl;
457  rstat = DuneFFT::fftInverse(dftOut, xdasOut, fftLogLevel);
458  if ( rstat ) {
459  cout << myname << "WARNING: Inverse xform failed. No action taken." << endl;
460  return ret.setStatus(4);
461  }
462  }
463 
464  // Direct convolution.
465  if ( m_doDirectConvolute ) {
466  if ( m_LogLevel >= 3 ) cout << myname << "Directly building time-domain output vector." << endl;
467  xdasOut.resize(nsam);
469  const FloatVector& xdasFld = m_useResponse ? xdasRes : m_useFilter ? xdasFil : empty;
470  for ( Index isam=0; isam<nsam; ++isam ) {
471  double xsam = 0.0;
472  for ( Index jsam=0; jsam<nsam; ++jsam ) {
473  Index imj = (isam + nsam - jsam) % nsam;
474  xsam += xdasInp[jsam]*xdasFld[imj];
475  }
476  xdasOut[isam] = xsam;
477  }
478  }
479 
480  // Deconvolution with matrix solve.
481  if ( m_directDeconvolute ) {
482  if ( m_LogLevel >= 1 ) cout << myname << "Deconvoluting with Root: option "
483  << m_directDeconvolute << "." << endl;
484  // Construct the response matrix from the response vector.
485  TMatrixDSparse mres(nsam, nsam);
486  if ( responseVectorToMatrix(responseVector, ishift, mres, m_LogLevel, myname) ) return ret.setStatus(6);
487  // Build data vector.
488  TVectorD vdat(nsam);
489  for ( Index isam=0; isam<nsam; ++isam ) {
490  vdat[isam] = xdasInp[isam];
491  }
492  // The following are alternatives to direct solution of vdat = mres q.
493  // The direct solution doesn't work because mres is ill conditioned.
494  // Either mres or mres and vdat are updated.
495  if ( m_directDeconvolute == 1 ) {
496  cout << "Performing direct matrix deconvolution." << endl;
497  } else if ( m_directDeconvolute == 2 ) {
498  cout << "Performing filtered matrix deconvolution." << endl;
499  // Filtered deconvolution.
500  // vdat = (mres mfil_inv) (mfil q)
501  // Doesn't work because mfil is ill conditioned.
502  // Build smearing vector vfil and matrix mfil.
503  DoubleVector vfil(smoothVector.begin(), smoothVector.end());
504  Index nfil = vfil.size();
505  TMatrixDSparse mfil(nsam, nsam);
506  if ( responseVectorToMatrix(vfil, nfil/2, mfil, m_LogLevel, myname) ) return ret.setStatus(7);
507  // Solve R_t = S_t (R Sinv)_t to get RSinv.
508  TMatrixDSparse mfil_t(nsam,nsam);
509  mfil_t.Transpose(mfil);
510  TMatrixD rsinv_t(nsam,nsam);
511  rsinv_t.Transpose(mres);
512  TDecompSVD ssolver(mfil_t);
513  if ( ssolver.Decompose() ) {
514  cout << myname << "Filtering condition is " << ssolver.Condition() << endl;
515  cout << myname << "S_t is " << (ssolver.GetMatrix().IsValid() ? "" : "not ") << "valid." << endl;
516  cout << myname << "R_t is " << (rsinv_t.IsValid() ? "" : "not ") << "valid." << endl;
517  ssolver.MultiSolve(rsinv_t);
518  cout << myname << "(R Sinv)_t is " << (rsinv_t.IsValid() ? "" : "not ") << "valid." << endl;
519  // Replace R with RSinv.
520  mres.Transpose(rsinv_t);
521  } else {
522  cout << myname << "Unable to decompose smearing matrix!" << endl;
523  return ret.setStatus(8);
524  }
525  // y = (R_t R + S_t S_t S) x
526  } else if ( m_directDeconvolute == 3 ) {
527  cout << "Performing chi-square matrix deconvolution." << endl;
528  TMatrixDSparse mres_t(nsam, nsam);
529  mres_t.Transpose(mres);
530  TMatrixDSparse mresres(mres_t);
531  mresres *= mres;
532  vdat *= mres_t;
533  vdat.Print();
534  // Fetch smearing vector vsmr and build matrix msmr.
535  DoubleVector vsmr(smoothVector.begin(), smoothVector.end());
536  for ( double& val : vsmr ) val*= smoothScale;
537  Index nsmr = vsmr.size();
538  TMatrixDSparse msmr(nsam, nsam);
539  if ( responseVectorToMatrix(vsmr, nsmr/2, msmr, m_LogLevel, myname) ) return ret.setStatus(9);
540  TMatrixDSparse msmr_t(nsam, nsam);
541  msmr_t.Transpose(msmr);
542  TMatrixDSparse msmrsmr(msmr_t);
543  msmrsmr *= msmr;
544  // Add smearing to reponse.
545  mres.SetSparseIndexAB(mresres, msmrsmr);
546  mres = mresres + msmrsmr;
547  } else if ( m_directDeconvolute == 4 ) {
548  DoubleVector vsmr = {0.05, 0.20, 0.5, 0.20, 0.05};
549  Index nsmr = vsmr.size();
550  TMatrixDSparse msmr(nsam, nsam);
551  if ( responseVectorToMatrix(vsmr, nsmr/2, msmr, m_LogLevel, myname) ) return ret.setStatus(9);
552  //vdat *= msmr;
553  msmr *= mres;
554  mres.SetSparseIndex(msmr);
555  mres = msmr;
556  } else if ( m_directDeconvolute != 1 ) {
557  return ret.setStatus(10);
558  }
559  // Solve vdat = mres q
560  //TDecompLU solver(mres);
561  TDecompSVD solver(mres);
562  if ( solver.Decompose() ) {
563  cout << myname << "Final matrix condition is " << solver.Condition() << endl;
564  solver.Solve(vdat);
565  for ( Index isam=0; isam<nsam; ++isam ) {
566  acd.samples[isam] = vdat[isam];
567  }
568  } else {
569  cout << myname << "Unable to decompose response matrix!" << endl;
570  return ret.setStatus(11);
571  }
572  } else {
573  // Record results from any other operation.
574  acd.samples = xdasOut;
575  if ( xamsOut.size() ) {
576  acd.dftmags = xamsOut;
577  acd.dftphases = xphsOut;
578  }
579  }
580 
581  return ret;
582 }
583 
584 //**********************************************************************
585 
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
FloatVector m_LowFilterWidths
unsigned int Index
DataMap & setStatus(int stat)
Definition: DataMap.h:130
std::string string
Definition: nybbler.cc:12
int setPhase(Index ifrq, F val)
FloatVector m_SmoothScales
constexpr T pow(T x)
Definition: pow.h:72
ResponseVectorVector m_SmoothVectors
AdcDeconvoluteFFT(fhicl::ParameterSet const &ps)
ChannelGroupService::Name Name
ResponseVectorVector m_ResponseVectors
static AdcIndex dftNormalization()
unsigned int Index
constexpr T square(T x)
Definition: pow.h:21
std::vector< float > FloatVector
CompactRealDftData< float > DFT
Definition: DuneFFT.h:28
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
static RealDftNormalization convolutionNormalization()
F amplitude(Index ifrq) const override
AdcSignalVector ResponseVector
Index nCompact() const override
F phase(Index ifrq) const override
Index nAmplitude() const
static int fftForward(Index ntick, const float *psam, DFT &dft, Index logLevel=0)
Definition: DuneFFT.cxx:23
IndexVector m_ResponseCenters
AdcIndex run() const
std::vector< double > DoubleVector
Definition: fcldump.cxx:27
AdcIndex event() const
AdcSignalVector dftphases
static constexpr double ps
Definition: Units.h:99
int setAmplitude(Index ifrq, F val)
DataMap update(AdcChannelData &acd) const override
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::unique_ptr< T > getPrivate(std::string name)
Channel channel() const
FloatVector m_LowFilterPowers
static int fftInverse(const DFT &dft, FloatVector &sams, Index logLevel=0)
Definition: DuneFFT.cxx:79
std::vector< AdcSignal > AdcSignalVector
Definition: AdcTypes.h:22
int moveIn(FloatVector &amps, FloatVector &phas)
IndexMapToolPtr m_channelToIndex
FloatVector m_GausFilterSigmas
Dft::FloatVector FloatVector
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
std::vector< ResponseVector > ResponseVectorVector
static DuneToolManager * instance(std::string fclname="", int dbg=1)
std::vector< Index > IndexVector
AdcSignalVector samples
AdcSignalVector dftmags
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)