247 const string myname =
"AdcDeconvoluteFFT::update: ";
250 if (
m_LogLevel >= 2 ) cout << myname <<
"Processing run " << acd.
run() <<
" event " << acd.
event()
251 <<
" channel " << icha <<
endl;
258 cout <<
"WARNING: There is no response vector for index " << ivec
259 <<
" (channel " << icha <<
")." <<
endl;
265 cout <<
"WARNING: There is no Gaus filter sigma for index " 266 << ivec <<
" (channel " << icha <<
")." <<
endl;
273 float lfwidth = -1.0;
276 cout <<
"WARNING: There is no low-filter width for index " 277 << ivec <<
" (channel " << icha <<
")." <<
endl;
281 cout <<
"WARNING: There is no low-filter width for index " 282 << ivec <<
" (channel " << icha <<
")." <<
endl;
299 Index nsam = xdasInp.size();
300 if ( nsam == 0 )
return ret;
304 Index nres = responseVector.size();
306 if (
m_LogLevel >= 3 ) cout << myname <<
"Building time-domain response vector." <<
endl;
308 cout << myname <<
"ERROR: Response function is undefined." <<
endl;
312 cout << myname <<
"WARNING: Data is shorter than the response function. No action taken." <<
endl;
315 for (
Index isam=0; isam<nres; ++isam ) {
316 Index jsam = isam >= ishift ? isam - ishift : nsam + isam - ishift;
317 xdasRes[jsam] = responseVector[isam];
324 DFT dftRes(fnormConv);
326 if (
m_LogLevel >= 3 ) cout << myname <<
"Using FFT to build frequency-domain response vectors." <<
endl;
329 cout << myname <<
"WARNING: Unable to xform response function. No action taken." <<
endl;
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);
343 DFT dftInp(fnormData);
346 if (
m_LogLevel >= 3 ) cout << myname <<
"Using FFT to build frequency-domain input vectors." <<
endl;
350 cout << myname <<
"WARNING: Unable to xform input data. No action taken." <<
endl;
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);
362 Index namp = dftInp.nAmplitude();
363 Index npha = dftInp.nPhase();
367 const float xmin = 1.e-20;
369 DFT dftFil(fnormConv);
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);
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;
393 dftFil.moveIn(xamsFil, xphsFil);
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);
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);
419 xamOut *= dftFil.amplitude(ifrq);
420 xphOut += dftFil.phase(ifrq);
422 xamOut *= dftRes.amplitude(ifrq);
423 xphOut += dftRes.phase(ifrq);
427 xamOut *= dftFil.amplitude(ifrq);
428 xphOut += dftFil.phase(ifrq);
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;
437 xphOut -= dftRes.phase(ifrq);
440 cout << myname <<
"ERROR: Unxpected error in FFT (de)convolution." <<
endl;
443 cout << myname <<
setw(4) << ifrq <<
": " <<
setw(10) << fixed << xamOut;
444 if ( ifrq < npha ) cout <<
" @ " <<
setw(10) << fixed << xphOut;
447 dftOut.setAmplitude(ifrq, xamOut);
448 xamsOut[ifrq] = xamOut;
450 dftOut.setPhase(ifrq, xphOut);
451 xphsOut[ifrq] = xphOut;
456 if (
m_LogLevel >= 3 ) cout << myname <<
"Using FFT to build time-domain output vector." <<
endl;
459 cout << myname <<
"WARNING: Inverse xform failed. No action taken." <<
endl;
466 if (
m_LogLevel >= 3 ) cout << myname <<
"Directly building time-domain output vector." <<
endl;
467 xdasOut.resize(nsam);
470 for (
Index isam=0; isam<nsam; ++isam ) {
472 for (
Index jsam=0; jsam<nsam; ++jsam ) {
473 Index imj = (isam + nsam - jsam) % nsam;
474 xsam += xdasInp[jsam]*xdasFld[imj];
476 xdasOut[isam] = xsam;
482 if (
m_LogLevel >= 1 ) cout << myname <<
"Deconvoluting with Root: option " 485 TMatrixDSparse mres(nsam, nsam);
486 if ( responseVectorToMatrix(responseVector, ishift, mres,
m_LogLevel, myname) )
return ret.
setStatus(6);
489 for (
Index isam=0; isam<nsam; ++isam ) {
490 vdat[isam] = xdasInp[isam];
496 cout <<
"Performing direct matrix deconvolution." <<
endl;
498 cout <<
"Performing filtered matrix deconvolution." <<
endl;
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);
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;
520 mres.Transpose(rsinv_t);
522 cout << myname <<
"Unable to decompose smearing matrix!" <<
endl;
527 cout <<
"Performing chi-square matrix deconvolution." <<
endl;
528 TMatrixDSparse mres_t(nsam, nsam);
529 mres_t.Transpose(mres);
530 TMatrixDSparse mresres(mres_t);
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);
545 mres.SetSparseIndexAB(mresres, msmrsmr);
546 mres = mresres + msmrsmr;
549 Index nsmr = vsmr.size();
550 TMatrixDSparse msmr(nsam, nsam);
551 if ( responseVectorToMatrix(vsmr, nsmr/2, msmr,
m_LogLevel, myname) )
return ret.
setStatus(9);
554 mres.SetSparseIndex(msmr);
561 TDecompSVD solver(mres);
562 if ( solver.Decompose() ) {
563 cout << myname <<
"Final matrix condition is " << solver.Condition() <<
endl;
565 for (
Index isam=0; isam<nsam; ++isam ) {
566 acd.
samples[isam] = vdat[isam];
569 cout << myname <<
"Unable to decompose response matrix!" <<
endl;
575 if ( xamsOut.size() ) {
FloatVector m_LowFilterWidths
DataMap & setStatus(int stat)
FloatVector m_SmoothScales
ResponseVectorVector m_SmoothVectors
ResponseVectorVector m_ResponseVectors
static AdcIndex dftNormalization()
static RealDftNormalization convolutionNormalization()
AdcSignalVector ResponseVector
static int fftForward(Index ntick, const float *psam, DFT &dft, Index logLevel=0)
IndexVector m_ResponseCenters
std::vector< double > DoubleVector
AdcSignalVector dftphases
Q_EXPORT QTSManip setw(int w)
FloatVector m_LowFilterPowers
static int fftInverse(const DFT &dft, FloatVector &sams, Index logLevel=0)
IndexMapToolPtr m_channelToIndex
FloatVector m_GausFilterSigmas
Dft::FloatVector FloatVector
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
QTextStream & endl(QTextStream &s)