NCFS-Pack
A generic (astro)particle physics analysis framework
 
Loading...
Searching...
No Matches
NcDSP.cxx
Go to the documentation of this file.
1
31
33
286
287#include "NcDSP.h"
288#include "Riostream.h"
289
290ClassImp(NcDSP); // Class implementation to enable ROOT I/O
291
293NcDSP::NcDSP(const char* name,const char* title) : TNamed(name,title)
294{
300
301 fProc=0;
302 Reset();
303 fSample=0;
304 fKeepOutput=kFALSE;
305}
306
308{
314
315 if (fProc)
316 {
317 delete fProc;
318 fProc=0;
319 }
320}
321
322NcDSP::NcDSP(const NcDSP& q) : TNamed(q)
323{
329
330 fProc=0;
331 fN=q.fN;
332 fNwf=q.fNwf;
333 fReIn=q.fReIn;
334 fImIn=q.fImIn;
335 fReOut=q.fReOut;
336 fImOut=q.fImOut;
337 fHisto=q.fHisto;
339 fNorm=q.fNorm;
342}
343
345{
351
352 if (fProc)
353 {
354 delete fProc;
355 fProc=0;
356 }
357 fN=0;
358 fNwf=0;
359 fReIn.Set(0);
360 fImIn.Set(0);
361 if (!fKeepOutput)
362 {
363 fReOut.Set(0);
364 fImOut.Set(0);
365 fHisto.Set(0);
366 }
367 fNorm="NONE";
368}
369
371{
380
381 fSample=f;
382}
383
385{
391
392 return fSample;
393}
394
395void NcDSP::Load(Int_t n,Double_t* re,Double_t* im,Float_t f)
396{
416
417 Reset();
418
419 if (f>=0) fSample=f;
420
421 if (n<1) return;
422
423 fN=n;
424 if (re) fReIn.Set(n);
425 if (im) fImIn.Set(n);
426
427 for (Int_t i=0; i<n; i++)
428 {
429 if (re) fReIn.SetAt(re[i],i);
430 if (im) fImIn.SetAt(im[i],i);
431 }
432}
433
434void NcDSP::Load(TArray* re,TArray* im,Float_t f)
435{
455
456 Reset();
457
458 if (f>=0) fSample=f;
459
460 Int_t nre=0;
461 Int_t nim=0;
462 if (re) nre=re->GetSize();
463 if (im) nim=im->GetSize();
464
465 Int_t n=nre;
466 if (!n) n=nim;
467 if (nre && nim>nre) n=nre;
468 if (nim && nre>nim) n=nim;
469
470 if (n<1) return;
471
472 fN=n;
473 if (nre) fReIn.Set(n);
474 if (nim) fImIn.Set(n);
475
476 Double_t valre=0;
477 Double_t valim=0;
478 for (Int_t i=0; i<n; i++)
479 {
480 if (nre)
481 {
482 valre=re->GetAt(i);
483 fReIn.SetAt(valre,i);
484 }
485 if (nim)
486 {
487 valim=im->GetAt(i);
488 fImIn.SetAt(valim,i);
489 }
490 }
491}
492
493void NcDSP::Load(NcSample* s,Int_t i,Float_t f)
494{
512
513 Reset();
514
515 if (f>=0) fSample=f;
516
517 if (!s)
518 {
519 cout << " *" << ClassName() <<"::Load* No input sample specified." << endl;
520 return;
521 }
522
523 Int_t n=s->GetN();
524 Int_t store=s->GetStoreMode();
525 Int_t dim=s->GetDimension();
526
527 if (n<1 || !store || dim<1 || i<1 || i>dim)
528 {
529 cout << " *" << ClassName() <<"::Load* Inconsistent input for NcSample treatment." << endl;
530 cout << " Store Mode:" << store << " Entries:" << n << " Dimension:" << dim << " i:" << i << " f:" << fSample << endl;
531 return;
532 }
533
534 fN=n;
535 fReIn.Set(n);
536
537 Double_t val=0;
538 for (Int_t idx=1; idx<=n; idx++)
539 {
540 val=s->GetEntry(idx,i);
541 fReIn.SetAt(val,idx-1);
542 }
543}
544
545void NcDSP::Load(NcSample* s,TString name,Float_t f)
546{
564
565 Reset();
566
567 if (f>=0) fSample=f;
568
569 if (!s)
570 {
571 cout << " *" << ClassName() <<"::Load* No input sample specified." << endl;
572 return;
573 }
574
575 Int_t n=s->GetN();
576 Int_t store=s->GetStoreMode();
577 Int_t dim=s->GetDimension();
578 Int_t i=s->GetIndex(name);
579
580
581 if (n<1 || !store || dim<1 || !i)
582 {
583 cout << " *" << ClassName() <<"::Load* Inconsistent input for NcSample treatment." << endl;
584 cout << " Store Mode:" << store << " Entries:" << n << " Dimension:" << dim << " name:" << name << " f:" << fSample << endl;
585 return;
586 }
587
588 Load(s,i,f);
589}
590
591void NcDSP::Load(TH1* h,Float_t f)
592{
608
609 Reset();
610
611 if (f>=0) fSample=f;
612
613 if (!h)
614 {
615 cout << " *" << ClassName() <<"::Load* No input histogram specified." << endl;
616 return;
617 }
618
619 Int_t nbins=h->GetNbinsX();
620 Double_t nentries=h->GetEntries();
621
622 if (!nbins || !nentries)
623 {
624 cout << " *" << ClassName() <<"::Load* Inconsistent input for histogram treatment." << endl;
625 cout << " Nbins:" << nbins << " Nentries:" << nentries << " f:" << fSample << endl;
626 return;
627 }
628
629 fN=nbins;
630 fReIn.Set(nbins);
631
632 Double_t val=0;
633 for (Int_t i=1; i<=nbins; i++)
634 {
635 val=h->GetBinContent(i);
636 fReIn.SetAt(val,i-1);
637 }
638}
639
640void NcDSP::Load(TGraph* gr,Float_t f)
641{
657
658 Reset();
659
660 if (f>=0) fSample=f;
661
662 if (!gr)
663 {
664 cout << " *" << ClassName() <<"::Load* No input TGraph object specified." << endl;
665 return;
666 }
667
668 Int_t n=gr->GetN();
669
670 if (!n)
671 {
672 cout << " *" << ClassName() <<"::Load* Inconsistent input for TGraph treatment." << endl;
673 cout << " n:" << n << " f:" << fSample << endl;
674 return;
675 }
676
677 fN=n;
678 fReIn.Set(n);
679
680 gr->Sort();
681
682 Double_t x=0;
683 Double_t y=0;
684 for (Int_t i=0; i<n; i++)
685 {
686 gr->GetPoint(i,x,y);
687 fReIn.SetAt(y,i);
688 }
689}
690
692{
708
711 fReOut.Set(0);
712 fImOut.Set(0);
713 fHisto.Set(0);
714}
715
716void NcDSP::SetWaveform(Int_t n,Double_t* h,Float_t f)
717{
736
737 fWaveform.Set(0);
738 fNwf=0;
739
740 if (f>=0) fSample=f;
741
742 if (!h)
743 {
744 cout << " *" << ClassName() <<"::SetWaveform* No data array specified." << endl;
745 return;
746 }
747
748 if (n<1) return;
749
750 fWaveform.Set(n);
751 fNwf=n;
752
753 for (Int_t i=0; i<n; i++)
754 {
755 fWaveform[i]=h[i];
756 }
757}
758
759void NcDSP::SetWaveform(TArray* h,Float_t f)
760{
776
777 fWaveform.Set(0);
778 fNwf=0;
779
780 if (f>=0) fSample=f;
781
782 if (!h)
783 {
784 cout << " *" << ClassName() <<"::SetWaveform* No data array specified." << endl;
785 return;
786 }
787
788 Int_t n=0;
789 if (h) n=h->GetSize();
790
791 if (n<1) return;
792
793 fWaveform.Set(n);
794 fNwf=n;
795
796 Double_t val=0;
797 for (Int_t i=0; i<n; i++)
798 {
799 val=h->GetAt(i);
800 fWaveform[i]=val;
801 }
802}
803
804void NcDSP::SetWaveform(NcSample* s,Int_t i,Float_t f)
805{
824
825 fWaveform.Set(0);
826 fNwf=0;
827
828 if (f>=0) fSample=f;
829
830 if (!s)
831 {
832 cout << " *" << ClassName() <<"::SetWaveform* No data sample specified." << endl;
833 return;
834 }
835
836 Int_t n=s->GetN();
837 Int_t store=s->GetStoreMode();
838 Int_t dim=s->GetDimension();
839
840 if (n<1 || !store || dim<1 || i<1 || i>dim)
841 {
842 cout << " *" << ClassName() <<"::SetWaveform* Inconsistent input for NcSample treatment." << endl;
843 cout << " Store Mode:" << store << " Entries:" << n << " Dimension:" << dim << " i:" << i << " f:" << fSample << endl;
844 return;
845 }
846
847 fWaveform.Set(n);
848 fNwf=n;
849
850 Double_t val=0;
851 for (Int_t idx=1; idx<=n; idx++)
852 {
853 val=s->GetEntry(idx,i);
854 fWaveform[idx-1]=val;
855 }
856}
857
858void NcDSP::SetWaveform(NcSample* s,TString name,Float_t f)
859{
878
879 fWaveform.Set(0);
880 fNwf=0;
881
882 if (f>=0) fSample=f;
883
884 if (!s)
885 {
886 cout << " *" << ClassName() <<"::SetWaveform* No data sample specified." << endl;
887 return;
888 }
889
890 Int_t n=s->GetN();
891 Int_t store=s->GetStoreMode();
892 Int_t dim=s->GetDimension();
893 Int_t i=s->GetIndex(name);
894
895
896 if (n<1 || !store || dim<1 || !i)
897 {
898 cout << " *" << ClassName() <<"::SetWaveform* Inconsistent input for NcSample treatment." << endl;
899 cout << " Store Mode:" << store << " Entries:" << n << " Dimension:" << dim << " name:" << name << " f:" << fSample << endl;
900 return;
901 }
902
903 SetWaveform(s,i,f);
904}
905
906void NcDSP::SetWaveform(TH1* h,Float_t f)
907{
923
924 fWaveform.Set(0);
925 fNwf=0;
926
927 if (f>=0) fSample=f;
928
929 if (!h)
930 {
931 cout << " *" << ClassName() <<"::SetWaveform* No input histogram specified." << endl;
932 return;
933 }
934
935 Int_t nbins=h->GetNbinsX();
936 Double_t nentries=h->GetEntries();
937
938 if (!nbins || !nentries)
939 {
940 cout << " *" << ClassName() <<"::SetWaveform* Inconsistent input for histogram treatment." << endl;
941 cout << " Nbins:" << nbins << " Nentries:" << nentries << " f:" << fSample << endl;
942 return;
943 }
944
945 fWaveform.Set(nbins);
946 fNwf=nbins;
947
948 Double_t val=0;
949 for (Int_t i=1; i<=nbins; i++)
950 {
951 val=h->GetBinContent(i);
952 fWaveform[i-1]=val;;
953 }
954}
955
956void NcDSP::SetWaveform(TGraph* gr,Float_t f)
957{
973
974 fWaveform.Set(0);
975 fNwf=0;
976
977 if (f>=0) fSample=f;
978
979 if (!gr)
980 {
981 cout << " *" << ClassName() <<"::SetWaveform* No input TGraph object specified." << endl;
982 return;
983 }
984
985 Int_t n=gr->GetN();
986
987 if (!n)
988 {
989 cout << " *" << ClassName() <<"::SetWaveform* Inconsistent input for TGraph treatment." << endl;
990 cout << " n:" << n << " f:" << fSample << endl;
991 return;
992 }
993
994 fWaveform.Set(n);
995 fNwf=n;
996
997 gr->Sort();
998
999 Double_t x=0;
1000 Double_t y=0;
1001 for (Int_t i=0; i<n; i++)
1002 {
1003 gr->GetPoint(i,x,y);
1004 fWaveform[i]=y;
1005 }
1006}
1007
1008Int_t NcDSP::GetN(Int_t mode) const
1009{
1020
1021 Int_t n=fN;
1022
1023 if (mode==1) n=fNwf;
1024
1025 return n;
1026}
1027
1028TArrayD NcDSP::GetData(TString sel) const
1029{
1054
1055 if (sel.Contains("RE") && sel.Contains("in")) return fReIn;
1056 if (sel.Contains("IM") && sel.Contains("in")) return fImIn;
1057 if (sel.Contains("RE") && sel.Contains("out")) return fReOut;
1058 if (sel.Contains("IM") && sel.Contains("out")) return fImOut;
1059 if (sel.Contains("Hist")) return fHisto;
1060 if (sel.Contains("Wave")) return fWaveform;
1061
1062 TArrayD data(fN);
1063 Double_t pi=acos(-1.);
1064 Double_t re=0;
1065 Double_t im=0;
1066 Double_t amp=0;
1067 Double_t phi=0;
1068 for (Int_t i=0; i<fN; i++)
1069 {
1070 if (sel.Contains("in"))
1071 {
1072 re=fReIn.At(i);
1073 im=fImIn.At(i);
1074 }
1075 if (sel.Contains("out"))
1076 {
1077 re=fReOut.At(i);
1078 im=fImOut.At(i);
1079 }
1080 amp=sqrt(re*re+im*im);
1081 phi=0;
1082 if (im || re) phi=atan2(im,re);
1083
1084 if (sel.Contains("AMP")) data.SetAt(amp,i);
1085 if (sel.Contains("PHIR")) data.SetAt(phi,i);
1086 if (sel.Contains("PHID")) data.SetAt(phi*180./pi,i);
1087 }
1088
1089 return data;
1090}
1091
1092void NcDSP::Fourier(TString mode,TH1* hist,TString sel)
1093{
1146
1147 fReOut.Set(0);
1148 fImOut.Set(0);
1149 fHisto.Set(0);
1150
1151 if (fN<1) return;
1152
1153 // Construct the Fast Fourier Transform (FFT) processor
1154 TString opt=mode;
1155 // Comply with the TVirtualFFT conventions
1156 if (mode=="C2C") opt="C2CFORWARD";
1157 if (mode=="C2CI") opt="C2CBACKWARD";
1158 // Set the optimalisation initialisation to "estimate" and create a new processor
1159 opt+=" ES K";
1160
1161 if (fProc)
1162 {
1163 delete fProc;
1164 fProc=0;
1165 }
1166
1167 fProc=TVirtualFFT::FFT(1,&fN,opt);
1168
1169 // Enter the input data
1170 Int_t nReIn=fReIn.GetSize();
1171 Int_t nImIn=fImIn.GetSize();
1172 if (mode=="R2C")
1173 {
1174 Double_t* data=fReIn.GetArray();
1175 fProc->SetPoints(data);
1176 }
1177 else
1178 {
1179 for (Int_t i=0; i<fN; i++)
1180 {
1181 if (nReIn && nImIn) fProc->SetPoint(i,fReIn[i],fImIn[i]);
1182 if (nReIn && !nImIn) fProc->SetPoint(i,fReIn[i],0);
1183 if (!nReIn && nImIn) fProc->SetPoint(i,0,fImIn[i]);
1184 }
1185 }
1186
1187 // Perform the Fast Fourier Transform
1188 fProc->Transform();
1189
1190 Double_t rN=fN;
1191
1192 // Copy the resulting data in the output arrays
1193 fReOut.Set(fN);
1194 fImOut.Set(fN);
1195 Double_t re=0;
1196 Double_t im=0;
1197 for (Int_t i=0; i<fN; i++)
1198 {
1199 fProc->GetPointComplex(i,re,im);
1200 re/=sqrt(rN);
1201 im/=sqrt(rN);
1202 fReOut[i]=re;
1203 fImOut[i]=im;
1204 }
1205
1206 Int_t imode=1;
1207 if (mode=="C2R" || mode=="C2CI") imode=-1;
1208 TString name;
1209 name.Form("DFT (%-s)",mode.Data());
1210 if (imode<0) name.Form("Inverse DFT (%-s)",mode.Data());
1211
1212 // Check for only domain specification specification
1213 TString opts[8]={"RE","IM","AMP","dB","PHIR","PHID","CPHI","SPHI"};
1214 Bool_t found=0;
1215 for (Int_t i=0; i<8; i++)
1216 {
1217 if (sel.Contains(opts[i]))
1218 {
1219 found=1;
1220 break;
1221 }
1222 }
1223
1224 if (!found)
1225 {
1226 if (sel.Contains("n") || sel.Contains("t")) // Time domain
1227 {
1228 if (mode=="C2C" || mode=="C2CI") sel+=" RE";
1229 }
1230 else // Frequency domain
1231 {
1232 sel+=" RE";
1233 }
1234 }
1235
1236 // Fill the requested histogram
1237 HistogramTrafoResult(name,imode,hist,sel);
1238}
1239
1240void NcDSP::Hartley(Int_t mode,TH1* hist,TString sel)
1241{
1291
1292 fReOut.Set(0);
1293 fImOut.Set(0);
1294 fHisto.Set(0);
1295
1296 if (!mode || fN<1) return;
1297
1298 // Construct the Fast Fourier Transform (FFT) processor
1299 if (fProc)
1300 {
1301 delete fProc;
1302 fProc=0;
1303 }
1304
1305 fProc=TVirtualFFT::FFT(1,&fN,"DHT ES K");
1306
1307 // Enter the input data
1308 Double_t* data=fReIn.GetArray();
1309 fProc->SetPoints(data);
1310
1311 // Perform the Discrete Hartley Transform
1312 fProc->Transform();
1313
1314 Double_t rN=fN;
1315
1316 // Copy the resulting data in the output arrays
1317 fReOut.Set(fN);
1318 fImOut.Set(0);
1319 Double_t re=0;
1320 for (Int_t i=0; i<fN; i++)
1321 {
1322 re=fProc->GetPointReal(i,kFALSE);
1323 re/=sqrt(rN);
1324 fReOut.SetAt(re,i);
1325 }
1326
1327 // Fill the requested histogram
1328 TString name="Discrete Hartley Transform (DHT)";
1329 if (mode<0) name="Inverse Discrete Hartley Transform (IDHT)";
1330
1331 HistogramTrafoResult(name,mode,hist,sel);
1332}
1333
1334void NcDSP::Cosine(Int_t type,TH1* hist,TString sel)
1335{
1389
1390 fReOut.Set(0);
1391 fImOut.Set(0);
1392 fHisto.Set(0);
1393
1394 if (abs(type)<1 || abs(type)>4 || fN<1 || (abs(type)==1 && fN<2)) return;
1395
1396 // Convert negative type specifications to the corresponding "normal" ones
1397 Int_t type2=type;
1398 if (type==-1 || type==-4) type2=abs(type);
1399 if (type==-2) type2=3;
1400 if (type==-3) type2=2;
1401
1402 // Comply with the TVirtualFFT conventions
1403 Int_t kind=type2-1;
1404
1405 // Construct the Fast Fourier Transform (FFT) processor
1406 if (fProc)
1407 {
1408 delete fProc;
1409 fProc=0;
1410 }
1411
1412 fProc=TVirtualFFT::SineCosine(1,&fN,&kind,"ES");
1413
1414 // Enter the input data
1415 Double_t* data=fReIn.GetArray();
1416 fProc->SetPoints(data);
1417
1418 // Perform the Discrete Cosine Transform
1419 fProc->Transform();
1420
1421 Double_t rN=fN;
1422
1423 // Copy the resulting data in the output arrays
1424 fReOut.Set(fN);
1425 fImOut.Set(0);
1426 Double_t re=0;
1427 for (Int_t i=0; i<fN; i++)
1428 {
1429 re=fProc->GetPointReal(i,kFALSE);
1430 if (type2==1)
1431 {
1432 re/=sqrt(2.*(rN-1.));
1433 }
1434 else
1435 {
1436 re/=sqrt(2.*rN);
1437 }
1438 fReOut[i]=re;
1439 }
1440
1441 TString name="Discrete Cosine Transform (DCT-";
1442 if (type<0) name="Inverse Discrete Cosine Transform (IDCT-";
1443 if (abs(type)==1) name+="I)";
1444 if (abs(type)==2) name+="II)";
1445 if (abs(type)==3) name+="III)";
1446 if (abs(type)==4) name+="IV)";
1447
1448 // Fill the requested histogram
1449 HistogramTrafoResult(name,type,hist,sel);
1450}
1451
1452void NcDSP::Sine(Int_t type,TH1* hist,TString sel)
1453{
1505
1506 fReOut.Set(0);
1507 fImOut.Set(0);
1508 fHisto.Set(0);
1509
1510 if (abs(type)<1 || abs(type)>4 || fN<1 || (abs(type)==1 && fN<2)) return;
1511
1512 // Convert negative type specifications to the corresponding "normal" ones
1513 Int_t type2=type;
1514 if (type==-1 || type==-4) type2=abs(type);
1515 if (type==-2) type2=3;
1516 if (type==-3) type2=2;
1517
1518 // Comply with the TVirtualFFT conventions
1519 Int_t kind=type2+3;
1520
1521 // Construct the Fast Fourier Transform (FFT) processor
1522 if (fProc)
1523 {
1524 delete fProc;
1525 fProc=0;
1526 }
1527
1528 fProc=TVirtualFFT::SineCosine(1,&fN,&kind,"ES K");
1529
1530 // Enter the input data
1531 Double_t* data=fReIn.GetArray();
1532 fProc->SetPoints(data);
1533
1534 // Perform the Discrete Cosine Transform
1535 fProc->Transform();
1536
1537 Double_t rN=fN;
1538
1539 // Copy the resulting data in the output arrays
1540 fReOut.Set(fN);
1541 fImOut.Set(0);
1542 Double_t re=0;
1543 for (Int_t i=0; i<fN; i++)
1544 {
1545 re=fProc->GetPointReal(i,kFALSE);
1546 if (type2==1)
1547 {
1548 re/=sqrt(2.*(rN+1.));
1549 }
1550 else
1551 {
1552 re/=sqrt(2.*rN);
1553 }
1554 fReOut[i]=re;
1555 }
1556
1557 TString name="Discrete Sine Transform (DST-";
1558 if (type<0) name="Inverse Discrete Sine Transform (IDST-";
1559 if (abs(type)==1) name+="I)";
1560 if (abs(type)==2) name+="II)";
1561 if (abs(type)==3) name+="III)";
1562 if (abs(type)==4) name+="IV)";
1563
1564 // Fill the requested histogram
1565 HistogramTrafoResult(name,type,hist,sel);
1566}
1567
1568void NcDSP::Hilbert(Int_t mode,TH1* hist,TString sel)
1569{
1668
1669 fReOut.Set(0);
1670 fImOut.Set(0);
1671 fHisto.Set(0);
1672
1673 if (!mode || fN<1) return;
1674
1675 // Save the original input array
1676 TArrayD temp=fReIn;
1677
1678 // Perform the DFT on X[] to obtain Q[]
1679 Fourier("R2C");
1680
1681 // Perform the Hilbert transformation in the frequency domain
1682 Double_t a=0;
1683 Double_t b=0;
1684 Double_t re=0;
1685 Double_t im=0;
1686 for (Int_t k=0; k<fN; k++)
1687 {
1688 a=fReOut[k];
1689 b=fImOut[k];
1690 re=0;
1691 im=0;
1692 if (k && k<=fN/2)
1693 {
1694 re=b;
1695 im=-a;
1696 }
1697 if (k>fN/2)
1698 {
1699 re=-b;
1700 im=a;
1701 }
1702 fReOut[k]=re;
1703 fImOut[k]=im;
1704 }
1705
1706 // Perform the inverse DFT on H[k] to obtain HT[n]
1707 TArrayD ReZ=fReIn; // The real part of the analytic signal
1708 LoadResult();
1709 Fourier("C2R");
1710 TArrayD ImZ=fReOut; // The imaginary part of the analytic signal
1711
1712 // Provide the analytic signal Z[n]=X[n]+i*HT[n] as intermediate output result
1713 if (mode>0) // Forward transformation
1714 {
1715 fReOut=ReZ;
1716 fImOut=ImZ;
1717 }
1718 else // Backward transformation
1719 {
1720 fImOut=ReZ;
1721 for (Int_t n=0; n<fN; n++)
1722 {
1723 fReOut[n]=-ImZ[n];
1724 }
1725 }
1726
1727 // Restore the original input array
1728 fReIn=temp;
1729
1730 // Check for only "n" or "t" specification
1731 TString opts[8]={"X","HT","AMP","dB","PHIR","PHID","CPHI","OMEGA"};
1732 Bool_t found=0;
1733 for (Int_t i=0; i<8; i++)
1734 {
1735 if (sel.Contains(opts[i]))
1736 {
1737 found=1;
1738 break;
1739 }
1740 }
1741
1742 if (!found)
1743 {
1744 if (mode>0) // Forward transformation
1745 {
1746 sel+=" HT";
1747 }
1748 else // Inverse transformation
1749 {
1750 sel+=" X";
1751 }
1752 }
1753
1754 // Convert the "X"and "HT" selections to the corresponding "RE" and "IM'.
1755 sel.ReplaceAll("X","RE");
1756 sel.ReplaceAll("HT","IM");
1757
1758 // Fill the requested histogram
1759 TString name="Discrete Hilbert Transform (DHIT)";
1760 if (mode<0) name="Inverse Discrete Hilbert Transform (IDHIT)";
1761
1762 HistogramTrafoResult(name,mode,hist,sel);
1763
1764 // Store the correct data array as real output
1765 if (mode>0) fReOut=ImZ; // Forward transformation
1766}
1767
1768void NcDSP::HistogramTrafoResult(TString name,Int_t mode,TH1* hist,TString sel)
1769{
1805
1806 fHisto.Set(0);
1807
1808 if (!mode || fN<1 || !hist) return;
1809
1810 Int_t n=1+fN/2;
1811 Float_t maxfrac=0.5;
1812 if (sel.Contains("n") || sel.Contains("t") || sel.Contains("2"))
1813 {
1814 n=fN;
1815 maxfrac=1;
1816 }
1817
1818 if ((sel.Contains("Hz") || sel.Contains("t") || sel.Contains("OMEGA")) && fSample<=0) return;
1819
1820 if (sel.Contains("OMEGA") && !(sel.Contains("n")) && !(sel.Contains("t"))) return;
1821
1822 hist->Reset();
1823
1824 // Initialize the histogram title
1825 TString title=name;
1826 title+=" ";
1827
1828 TString title2="";
1829
1830 // Define and fill the requested result histogram
1831 if (sel.Contains("k"))
1832 {
1833 hist->SetBins(n,0,n-1);
1834 title+="index frequency domain";
1835 if (mode<0)
1836 {
1837 title+=" (input)";
1838 }
1839 else if (fSample>0)
1840 {
1841 title2.Form(" (DAQ: %-.3g samples/sec)",fSample);
1842 title+=title2;
1843 }
1844 title+=";Index k";
1845 if (sel.Contains("RE")) title+=";Re(Q[k])";
1846 if (sel.Contains("IM")) title+=";Im(Q[k])";
1847 if (sel.Contains("AMP")) title+=";Amplitude |Q[k]|";
1848 if (sel.Contains("dB")) title+=";Amplitude |Q[k]| in dB";
1849 if (sel.Contains("PHIR")) title+=";Phase #varphi[k] (rad)";
1850 if (sel.Contains("PHID")) title+=";Phase #varphi[k] (deg)";
1851 if (sel.Contains("CPHI")) title+=";cos(#varphi[k])";
1852 if (sel.Contains("SPHI")) title+=";sin(#varphi[k])";
1853 if (!(title.Contains("[k]")))
1854 {
1855 sel+=" RE";
1856 title+=";Value Q[k]";
1857 }
1858 }
1859 if (sel.Contains("f"))
1860 {
1861 hist->SetBins(n,0,maxfrac);
1862 title+="fractional frequency domain";
1863 if (mode<0)
1864 {
1865 title+=" (input)";
1866 }
1867 else if (fSample>0)
1868 {
1869 title2.Form(" (DAQ: %-.3g samples/sec)",fSample);
1870 title+=title2;
1871 }
1872 title+=";Fraction f of sampling rate";
1873 if (sel.Contains("RE")) title+=";Re(Q[f])";
1874 if (sel.Contains("IM")) title+=";Im(Q[f])";
1875 if (sel.Contains("AMP")) title+=";Amplitude |Q[f]|";
1876 if (sel.Contains("dB")) title+=";Amplitude |Q[f]| in dB";
1877 if (sel.Contains("PHIR")) title+=";Phase #varphi[f] (rad)";
1878 if (sel.Contains("PHID")) title+=";Phase #varphi[f] (deg)";
1879 if (sel.Contains("CPHI")) title+=";cos(#varphi[f])";
1880 if (sel.Contains("SPHI")) title+=";sin(#varphi[f])";
1881 if (!(title.Contains("[f]")))
1882 {
1883 sel+=" RE";
1884 title+=";Value Q[f]";
1885 }
1886 }
1887 if (sel.Contains("Hz"))
1888 {
1889 hist->SetBins(n,0,maxfrac*fSample);
1890 title+="actual frequency domain";
1891 if (mode<0)
1892 {
1893 title+=" (input)";
1894 }
1895 else if (fSample>0)
1896 {
1897 title2.Form(" (DAQ: %-.3g samples/sec)",fSample);
1898 title+=title2;
1899 }
1900 title+=";Frequency #nu (Hz)";
1901 if (sel.Contains("RE")) title+=";Re(Q[#nu])";
1902 if (sel.Contains("IM")) title+=";Im(Q[#nu])";
1903 if (sel.Contains("AMP")) title+=";Amplitude |Q[#nu]|";
1904 if (sel.Contains("dB")) title+=";Amplitude |Q[#nu]| in dB";
1905 if (sel.Contains("PHIR")) title+=";Phase #varphi[#nu] (rad)";
1906 if (sel.Contains("PHID")) title+=";Phase #varphi[#nu] (deg)";
1907 if (sel.Contains("CPHI")) title+=";cos(#varphi[#nu])";
1908 if (sel.Contains("SPHI")) title+=";sin(#varphi[#nu])";
1909 if (!(title.Contains("[#nu]")))
1910 {
1911 sel+=" RE";
1912 title+=";Value Q[#nu]";
1913 }
1914 }
1915
1916 if (sel.Contains("n"))
1917 {
1918 hist->SetBins(fN,0,fN);
1919 title+="sampling time domain";
1920 if (mode>0 && !(name.Contains("Hilbert"))) title+=" input";
1921 if (fSample>0) title2.Form(" (DAQ: %-.3g samples/sec)",fSample);
1922 title+=title2;
1923 title+=";Sample number n";
1924 if (name.Contains("Hilbert"))
1925 {
1926 if (sel.Contains("RE")) title+=";Value X[n]";
1927 if (sel.Contains("IM")) title+=";Value HT[n]";
1928 if (sel.Contains("AMP")) title+=";Amplitude |Z[n]|";
1929 if (sel.Contains("dB")) title+=";Amplitude |Z[n]| in dB";
1930 }
1931 else
1932 {
1933 if (sel.Contains("RE")) title+=";Re(X[n])";
1934 if (sel.Contains("IM")) title+=";Im(X[n])";
1935 if (sel.Contains("AMP")) title+=";Amplitude |X[n]|";
1936 if (sel.Contains("dB")) title+=";Amplitude |X[n]| in dB";
1937 }
1938 if (sel.Contains("PHIR")) title+=";Phase #varphi[n] (rad)";
1939 if (sel.Contains("PHID")) title+=";Phase #varphi[n] (deg)";
1940 if (sel.Contains("CPHI")) title+=";cos(#varphi[n])";
1941 if (sel.Contains("SPHI")) title+=";sin(#varphi[n])";
1942 if (sel.Contains("OMEGA")) title+=";#omega[n] (rad/s)";
1943 if (!(title.Contains("[n]")))
1944 {
1945 sel+=" RE";
1946 title+=";Value X[n]";
1947 }
1948 }
1949 if (sel.Contains("t"))
1950 {
1951 hist->SetBins(fN,0,double(fN)/fSample);
1952 title+="actual time domain";
1953 if (mode>0 && !(name.Contains("Hilbert"))) title+=" input";
1954 if (fSample>0) title2.Form(" (DAQ: %-.3g samples/sec)",fSample);
1955 title+=title2;
1956 title+=";Time t (seconds)";
1957 if (name.Contains("Hilbert"))
1958 {
1959 if (sel.Contains("RE")) title+=";Value X[t]";
1960 if (sel.Contains("IM")) title+=";Value HT[t]";
1961 if (sel.Contains("AMP")) title+=";Amplitude |Z[t]|";
1962 if (sel.Contains("dB")) title+=";Amplitude |Z[t]| in dB";
1963 }
1964 else
1965 {
1966 if (sel.Contains("RE")) title+=";Re(X[t])";
1967 if (sel.Contains("IM")) title+=";Im(X[t])";
1968 if (sel.Contains("AMP")) title+=";Amplitude |X[t]|";
1969 if (sel.Contains("dB")) title+=";Amplitude |X[t]| in dB";
1970 }
1971 if (sel.Contains("PHIR")) title+=";Phase #varphi[t] (rad)";
1972 if (sel.Contains("PHID")) title+=";Phase #varphi[t] (deg)";
1973 if (sel.Contains("CPHI")) title+=";cos(#varphi[t])";
1974 if (sel.Contains("SPHI")) title+=";sin(#varphi[t])";
1975 if (sel.Contains("OMEGA")) title+=";#omega[t] (rad/s)";
1976 if (!(title.Contains("[t]")))
1977 {
1978 sel+=" RE";
1979 title+=";Value X[t]";
1980 }
1981 }
1982
1983 hist->SetTitle(title);
1984
1985 Int_t nReIn=fReIn.GetSize();
1986 Int_t nImIn=fImIn.GetSize();
1987 Int_t nReOut=fReOut.GetSize();
1988 Int_t nImOut=fImOut.GetSize();
1989 Double_t pi=acos(-1.);
1990 Double_t amp=0;
1991 Double_t phi=0;
1992 Double_t cphi=0;
1993 Double_t sphi=0;
1994 Double_t omega=0;
1995 Double_t re=0;
1996 Double_t im=0;
1997 Double_t re2=0;
1998 Double_t im2=0;
1999 Double_t phi2=0;
2000 fHisto.Set(n);
2001
2002 // Determine stepsize in fractional sampling frequency for the Cosine and Sine transformation
2003 Double_t fstep=1./(2.*double(fN));
2004 if (name.Contains("DCT-I") && fN>1) fstep=1./(2.*double(fN-1));
2005 if (name.Contains("DST-I")) fstep=1./(2.*double(fN+1));
2006
2007 Double_t x=-1;
2008 for (Int_t i=0; i<n; i++)
2009 {
2010 if (name.Contains("DCT-"))
2011 {
2012 x=i;
2013 if (mode==3 || mode==-2 || abs(mode)==4) x+=0.5;
2014 }
2015 if (name.Contains("DST-"))
2016 {
2017 x=i+1;
2018 if (mode==3 || mode==-2 || abs(mode)==4) x-=0.5;
2019 }
2020 x*=fstep;
2021 if (sel.Contains("Hz")) x*=fSample;
2022
2023 if (sel.Contains("n") || sel.Contains("t")) // Time domain data requested
2024 {
2025 if (mode>0) // Forward transformation
2026 {
2027 if (name.Contains("Hilbert"))
2028 {
2029 if (nReOut)
2030 {
2031 re=fReOut[i];
2032 if (i<n-1) re2=fReOut[i+1];
2033 }
2034 if (nImOut)
2035 {
2036 im=fImOut[i];
2037 if (i<n-1) im2=fImOut[i+1];
2038 }
2039 }
2040 else
2041 {
2042 if (nReIn) re=fReIn[i];
2043 if (nImIn) im=fImIn[i];
2044 }
2045 }
2046 if (mode<0) // Inverse transformation
2047 {
2048 if (nReOut) re=fReOut[i];
2049 if (nImOut) im=fImOut[i];
2050 if (name.Contains("Hilbert") && i<n-1)
2051 {
2052 if (nReOut) re2=fReOut[i+1];
2053 if (nImOut) im2=fImOut[i+1];
2054 }
2055 }
2056 }
2057 else // Frequency domain data requested
2058 {
2059 if (mode<0) // Inverse transformation
2060 {
2061 if (nReIn) re=fReIn[i];
2062 if (nImIn) im=fImIn[i];
2063 }
2064 else // Forward transformation
2065 {
2066 if (nReOut) re=fReOut[i];
2067 if (nImOut) im=fImOut[i];
2068 }
2069 }
2070 if (name.Contains("DCT-") || name.Contains("DST-"))
2071 {
2072 if (sel.Contains("f") || sel.Contains("Hz"))
2073 {
2074 hist->Fill(x,re);
2075 }
2076 else
2077 {
2078 hist->SetBinContent(i+1,re);
2079 }
2080 }
2081 else
2082 {
2083 amp=sqrt(re*re+im*im);
2084 phi=0;
2085 if (im || re) phi=atan2(im,re);
2086 cphi=cos(phi);
2087 sphi=sin(phi);
2088 phi2=0;
2089 if (fSample>0 && i<n-1 && (im2 || re2))
2090 {
2091 phi2=atan2(im2,re2);
2092 if ((phi2*phi)>=0) omega=fabs(phi2-phi)*fSample;
2093 }
2094 if (sel.Contains("RE")) hist->SetBinContent(i+1,re);
2095 if (sel.Contains("IM")) hist->SetBinContent(i+1,im);
2096 if (sel.Contains("AMP")) hist->SetBinContent(i+1,amp);
2097 if (amp<=0) amp=hist->GetMinimum();
2098 if (sel.Contains("dB"))
2099 {
2100 // Check for rounding errors
2101 if (amp<=0)
2102 {
2103 amp=hist->GetMinimum();
2104 hist->SetBinContent(i+1,amp);
2105 }
2106 else
2107 {
2108 hist->SetBinContent(i+1,20.*log10(amp));
2109 }
2110 }
2111 if (sel.Contains("PHIR")) hist->SetBinContent(i+1,phi);
2112 if (sel.Contains("PHID")) hist->SetBinContent(i+1,phi*180./pi);
2113 if (sel.Contains("CPHI")) hist->SetBinContent(i+1,cphi);
2114 if (sel.Contains("SPHI")) hist->SetBinContent(i+1,sphi);
2115 if (sel.Contains("OMEGA")) hist->SetBinContent(i+1,omega);
2116 }
2117 }
2118
2119 // Fill the fHisto array with the histogram contents
2120 for (Int_t i=0; i<n; i++)
2121 {
2122 fHisto[i]=hist->GetBinContent(i+1);
2123 }
2124}
2125
2126TArrayD NcDSP::Convolve(TH1* hist,Int_t* i1,Int_t* i2,Int_t shift)
2127{
2190
2191 TArrayD y(0);
2192 if (hist) hist->Reset();
2193
2194 TArrayD x=fReIn;
2195 TArrayD h=fWaveform;
2196 Int_t nx=x.GetSize();
2197 Int_t nh=h.GetSize();
2198
2199 if (nh<1 || nx<1)
2200 {
2201 printf(" *%-s::Convolve* Input or Waveform data are missing. Ninput=%-i Nwaveform=%-i \n",ClassName(),nx,nh);
2202 return y;
2203 }
2204
2205 if (shift<0 || shift>2)
2206 {
2207 printf(" *%-s::Convolve* Invalid input argument shift=%-i \n",ClassName(),shift);
2208 return y;
2209 }
2210
2211 Int_t ny=nx+nh-1;
2212 y.Set(ny);
2213
2214 // The normalization data for correlation studies
2215 TArrayD x1(ny);
2216 TArrayD x2(ny);
2217 TArrayD h1(ny);
2218 TArrayD h2(ny);
2219 TArrayI ns(ny);
2220
2221 // Convolution from the input signal viewpoint
2222 for (Int_t ix=0; ix<nx; ix++)
2223 {
2224 for (Int_t ih=0; ih<nh; ih++)
2225 {
2226 // Perform the unnormalized convolution
2227 y[ix+ih]=y[ix+ih]+x[ix]*h[ih];
2228
2229 if (fNorm=="NONE" || fNorm=="GNCC") continue;
2230
2231 // Gather the normalization data for the "NCC" and "ZNCC" cross-correlation studies
2232 x1[ix+ih]+=x[ix];
2233 x2[ix+ih]+=pow(x[ix],2);
2234 h1[ix+ih]+=h[ih];
2235 h2[ix+ih]+=pow(h[ih],2);
2236 ns[ix+ih]+=1;
2237 }
2238 }
2239
2240 // Normalize values for cross-correlation studies if requested
2241 if (fNorm!="NONE")
2242 {
2243 Double_t val=0;
2244 if (fNorm=="GNCC") // Global vector length normalization
2245 {
2246 Double_t xnorm=0;
2247 Double_t hnorm=0;
2248 for (Int_t i=0; i<nx; i++)
2249 {
2250 xnorm+=pow(x[i],2);
2251 }
2252 for (Int_t i=0; i<nh; i++)
2253 {
2254 hnorm+=pow(h[i],2);
2255 }
2256 xnorm=sqrt(xnorm);
2257 hnorm=sqrt(hnorm);
2258 for (Int_t i=0; i<ny; i++)
2259 {
2260 val=xnorm*hnorm;
2261 if (val>0) y[i]=y[i]/val;
2262 }
2263 }
2264 else if (fNorm=="NCC") // NCC normalization
2265 {
2266 for (Int_t i=0; i<ny; i++)
2267 {
2268 val=sqrt(x2[i]*h2[i]);
2269 if (val>0) y[i]=y[i]/val;
2270 }
2271 }
2272 else // ZNCC normalization
2273 {
2274 y.Reset();
2275 Double_t x1mean=0;
2276 Double_t h1mean=0;
2277 Double_t x2mean=0;
2278 Double_t h2mean=0;
2279 Double_t rn=0;
2280 Double_t sx=0;
2281 Double_t sh=0;
2282 Double_t sxsh=0;
2283 Int_t iy=0;
2284 for (Int_t ix=0; ix<nx; ix++)
2285 {
2286 for (Int_t ih=0; ih<nh; ih++)
2287 {
2288 iy=ix+ih;
2289
2290 if (!ns[iy]) continue;
2291
2292 rn=ns[iy];
2293 x1mean=x1[iy]/rn;
2294 x2mean=x2[iy]/rn;
2295 h1mean=h1[iy]/rn;
2296 h2mean=h2[iy]/rn;
2297 sx=sqrt(x2mean-pow(x1mean,2));
2298 sh=sqrt(h2mean-pow(h1mean,2));
2299 sxsh=sx*sh;
2300 val=0;
2301 if (sxsh>0) val=(x[ix]-x1mean)*(h[ih]-h1mean)/(rn*sxsh);
2302 y[iy]+=val;
2303 }
2304 }
2305 }
2306 }
2307
2308 Int_t ilow=nh-1;
2309 Int_t iup=ny-nh;
2310
2311 Int_t ioffset=0;
2312 if (shift==2)
2313 {
2314 ioffset=nh/2;
2315 TArrayD temp(nx);
2316 for (Int_t i=0; i<nx; i++)
2317 {
2318 temp[i]=y[i+ioffset];
2319 }
2320 y=temp;
2321 ny=nx;
2322 ilow=ilow-ioffset;
2323 iup=iup-ioffset;
2324 }
2325
2326 if (i1) *i1=ilow;
2327 if (i2) *i2=iup;
2328
2329 if (hist)
2330 {
2331 TString title;
2332 if (fSample>0)
2333 {
2334 title.Form("NcDSP Convolution result (%-g samples/sec);Time in seconds;Value",fSample);
2335 if (shift==0 || shift==2)
2336 {
2337 hist->SetBins(ny,0,double(ny)/fSample);
2338 }
2339 else
2340 {
2341 hist->SetBins(ny,double(-nh+1)/fSample,double(nx)/fSample);
2342 }
2343 }
2344 else
2345 {
2346 title.Form("NcDSP Convolution result;Sample number;Value");
2347 if (shift==0 || shift==2)
2348 {
2349 hist->SetBins(ny,0,ny);
2350 }
2351 else
2352 {
2353 hist->SetBins(ny,-nh+1,nx);
2354 }
2355 }
2356
2357 hist->SetTitle(title);
2358 hist->SetMarkerStyle(20);
2359 for (Int_t ibin=1; ibin<=ny; ibin++)
2360 {
2361 hist->SetBinContent(ibin,y[ibin-1]);
2362 }
2363
2364 Double_t ymin=hist->GetMinimum();
2365 Double_t ymax=hist->GetMaximum();
2366
2367 Double_t xlow=0;
2368 Double_t xup=0;
2369 if (i1) xlow=hist->GetBinLowEdge(ilow+1);
2370 if (i2)
2371 {
2372 xup=hist->GetBinLowEdge(iup+1);
2373 xup+=hist->GetBinWidth(1);
2374 }
2375
2376 TLine* vline1=0;
2377 TLine* vline2=0;
2378
2379 if (i1)
2380 {
2381 vline1=new TLine(xlow,ymin,xlow,ymax);
2382 vline1->SetLineStyle(2); // Dashed line
2383 vline1->SetLineWidth(2);
2384 vline1->SetLineColor(4); // Blue color
2385 }
2386 if (i2)
2387 {
2388 vline2=new TLine(xup,ymin,xup,ymax);
2389 vline2->SetLineStyle(2); // Dashed line
2390 vline2->SetLineWidth(2);
2391 vline2->SetLineColor(4); // Blue color
2392 }
2393
2394 TList* hlist=hist->GetListOfFunctions();
2395 if (vline1) hlist->Add(vline1);
2396 if (vline2) hlist->Add(vline2);
2397 }
2398
2399 return y;
2400}
2401
2402TArrayD NcDSP::Correlate(TH1* hist,Int_t* i1,Int_t* i2,Double_t* peak,TString norm)
2403{
2471
2472 TArrayD y(0);
2473 if (hist) hist->Reset();
2474 Int_t nx=fReIn.GetSize();
2475 Int_t nh=fWaveform.GetSize();
2476
2477 if (nh<1 || nx<1)
2478 {
2479 printf(" *%-s::Correlate* Input or Waveform data are missing. Ninput=%-i Nwaveform=%-i \n",ClassName(),nx,nh);
2480 return y;
2481 }
2482
2483 norm.ToUpper(); // Convert norm to uppercase characters
2484 if (norm!="NONE" && norm!="GNCC" && norm!="NCC" && norm!="ZNCC")
2485 {
2486 printf(" *%-s::Correlate* Unsupported normalization mode : norm=%-s \n",ClassName(),norm.Data());
2487 return y;
2488 }
2489
2490 // The temporary "flipped" waveform
2491 TArrayD store=fWaveform;
2492 TArrayD temp(nh);
2493 for (Int_t i=1; i<=nh; i++)
2494 {
2495 temp[i-1]=fWaveform[nh-i];
2496 }
2497
2498 fWaveform=temp;
2499 fNorm=norm; // Normalize the correlation values if requested
2500 y=Convolve(hist,i1,i2,1);
2501 fNorm="NONE"; // Reset the normalization indicator for convolution studies
2502
2503 // Get the index of the maximum in the y[] array
2504 Int_t imax=0;
2505 Double_t ymax=0;
2506 Int_t ny=y.GetSize();
2507 if (ny) ymax=y[0];
2508 for (Int_t i=1; i<ny; i++)
2509 {
2510 if (y[i]>ymax)
2511 {
2512 ymax=y[i];
2513 imax=i;
2514 }
2515 }
2516
2517 // Convert to the index matching the x[] convention
2518 Int_t idx=imax-nh+1;
2519 Double_t xpeak=idx;
2520 if (fSample>0) xpeak=xpeak/fSample;
2521
2522 if (peak) *peak=xpeak;
2523
2524 // Put the correct histogram title
2525 if (hist)
2526 {
2527 TString title;
2528 if (fSample>0)
2529 {
2530 if (norm=="NCC")
2531 {
2532 title.Form("%-s Normalized Cross-Correlation (NCC): max. at lag=%-g sec. (%-g samples/sec)",ClassName(),xpeak,fSample);
2533 }
2534 else if (norm=="ZNCC")
2535 {
2536 title.Form("%-s Zero-Normalized Cross-Correlation (ZNCC): max. at lag=%-g sec. (%-g samples/sec)",ClassName(),xpeak,fSample);
2537 }
2538 else if (norm=="GNCC")
2539 {
2540 title.Form("%-s Globally Normalized Cross-Correlation (GNCC): max. at lag=%-g sec. (%-g samples/sec)",ClassName(),xpeak,fSample);
2541 }
2542 else
2543 {
2544 title.Form("%-s Unnormalized Cross-Correlation: max. at lag=%-g sec. (%-g samples/sec)",ClassName(),xpeak,fSample);
2545 }
2546 title+=";Time lag in seconds;Cross-Correlation value";
2547 }
2548 else
2549 {
2550 if (norm=="NCC")
2551 {
2552 title.Form("%-s Normalized Cross-Correlation (NCC): max. at lag=%-i samplings",ClassName(),idx);
2553 }
2554 else if (norm=="ZNCC")
2555 {
2556 title.Form("%-s Zero-Normalized Cross-Correlation (ZNCC): max. at lag=%-i samplings",ClassName(),idx);
2557 }
2558 else if (norm=="GNCC")
2559 {
2560 title.Form("%-s Gobally Normalized Cross-Correlation (GNCC): max. at lag=%-i samplings",ClassName(),idx);
2561 }
2562 else
2563 {
2564 title.Form("%-s Unnormalized Cross-Correlation: max. at lag=%-i samplings",ClassName(),idx);
2565 }
2566 title+=";Lag in samplings;Cross-Correlation value";
2567 }
2568 hist->SetTitle(title);
2569 }
2570
2571 // Restore the original waveform
2572 fWaveform=store;
2573
2574 return y;
2575}
2576
2577TArrayD NcDSP::Digitize(Int_t nbits,Double_t vcal,Int_t mode,TH1* hist,Double_t* stp,Double_t* scale) const
2578{
2641
2642 TArrayD arrdig(0);
2643 if (hist) hist->Reset();
2644
2645 if (mode<0 || mode>3)
2646 {
2647 cout << " *" << ClassName() << "::Digitize* Inconsistent input mode=" << mode << endl;
2648 return arrdig;
2649 }
2650
2651 if (!nbits || nbits>60 || nbits<-60 || fabs(vcal)<=0)
2652 {
2653 cout << " *" << ClassName() << "::Digitize* Inconsistent input nbits=" << nbits << " vcal=" << vcal << endl;
2654 return arrdig;
2655 }
2656
2657 if ((mode==1 || mode==3) && nbits==1)
2658 {
2659 cout << " *" << ClassName() << "::Digitize* Inconsistent input nbits=" << nbits << " mode=" << mode << endl;
2660 return arrdig;
2661 }
2662
2663 Bool_t logmode=kFALSE;
2664 if (nbits<0) logmode=kTRUE;
2665
2666 nbits=abs(nbits);
2667
2668 Long_t nlevels=pow(2,nbits);
2669 Double_t range=fabs(vcal);
2670 if (mode==1 || mode==3) range*=2.;
2671 Double_t step=fabs(vcal);
2672 if (mode==0) step=range/double(nlevels-1);
2673 if (mode==1) step=range/double(nlevels-2);
2674
2675 if (step<=0) return arrdig;
2676
2677 Long_t nstepsmin=0;
2678 Long_t nstepsmax=nlevels-1;
2679 if ((mode==0 || mode==2) && vcal<0)
2680 {
2681 nstepsmin=-nlevels+1;
2682 nstepsmax=0;
2683 }
2684 if (mode==1 || mode==3)
2685 {
2686 nstepsmin=-nlevels/2;
2687 nstepsmax=nlevels/2-1;
2688 }
2689
2690 Double_t digvalmin=double(nstepsmin)*step;
2691 Double_t digvalmax=double(nstepsmax)*step;
2692
2693 cout << " *" << ClassName() << "::Digitize* Parameters of the " << nbits << "-bits";
2694 if (logmode) cout << " Log10";
2695 cout << " ADC digitization." << endl;
2696 TString s="linear";
2697 if (logmode) s="Log10";
2698 if (mode==0 || mode==2)
2699 {
2700 cout << " Digitized " << s << " full scale range : [" << digvalmin << "," << digvalmax << "] Step size : " << step << endl;
2701 }
2702 if (mode==1 || mode==3)
2703 {
2704 cout << " Digitized " << s << " full scale range : [" << (digvalmin+step) << "," << digvalmax << "] Step size : " << step;
2705 cout << " Actual range : [" << digvalmin << "," << digvalmax << "]" << endl;
2706 }
2707
2708 if (logmode)
2709 {
2710 Double_t linvalmin=pow(10,digvalmin);
2711 Double_t linvalmax=pow(10,digvalmax);
2712 if (mode==0 || mode==2)
2713 {
2714 cout << " Digitized linear full scale range : [" << linvalmin << "," << linvalmax << "]" << endl;
2715 }
2716 if (mode==1 || mode==3)
2717 {
2718 cout << " Digitized linear full scale range : [" << (linvalmin*pow(10,step)) << "," << linvalmax << "]";
2719 cout << " Actual range : [" << linvalmin << "," << linvalmax << "]" << endl;
2720 }
2721 }
2722
2723 if (stp) *stp=step;
2724 if (scale)
2725 {
2726 *scale=fabs(vcal);
2727 if (mode==2)
2728 {
2729 if (vcal<0) *scale=digvalmin;
2730 if (vcal>0) *scale=digvalmax;
2731 }
2732 if (mode==3) *scale=digvalmax;
2733 }
2734
2735 if (fNwf<1)
2736 {
2737 printf(" === No waveform data present: Only listing of ADC specs.===\n");
2738 return arrdig;
2739 }
2740
2741 arrdig.Set(fNwf);
2742
2743 if (hist)
2744 {
2745 TString title;
2746 if (fSample>0)
2747 {
2748 hist->SetBins(fNwf,0,double(fNwf)/fSample);
2749 title.Form("NcDSP Digitize result (%-g samples/sec);Time in seconds;Value",fSample);
2750 }
2751 else
2752 {
2753 title.Form("NcDSP Digitize result;Sample number;Value");
2754 hist->SetBins(fNwf,0,fNwf);
2755 }
2756 hist->SetMarkerStyle(20);
2757 hist->SetTitle(title);
2758 }
2759
2760 Double_t val=0;
2761 Long_t nsteps=0;
2762 Double_t digval=0;
2763 for (Int_t j=0; j<fNwf; j++)
2764 {
2765 val=fWaveform[j];
2766
2767 if (logmode)
2768 {
2769 if (val>0)
2770 {
2771 val=log10(val);
2772 }
2773 else
2774 {
2775 cout << endl;
2776 cout << " *" << ClassName() << "::Digitize* Error: Non-positive input value encountered for Log10 ADC." << endl;
2777 arrdig.Set(0);
2778 return arrdig;
2779 }
2780 }
2781 nsteps=val/step;
2782
2783 if (nsteps<nstepsmin) nsteps=nstepsmin;
2784 if (nsteps>nstepsmax) nsteps=nstepsmax;
2785
2786 digval=double(nsteps)*step;
2787
2788 if (logmode) digval=pow(10,digval);
2789
2790 arrdig[j]=digval;
2791
2792 if (hist) hist->SetBinContent(j+1,digval);
2793 }
2794
2795 return arrdig;
2796}
2797
2798TArrayL64 NcDSP::ADC(Int_t nbits,Double_t range,Double_t Vbias,TArray* Vsig,TH1* hist,Int_t B,Int_t C) const
2799{
2884
2885 TArrayL64 arradc(0);
2886 if (hist) hist->Reset();
2887
2888 if (!Vsig) Vsig=(TArray*)&fWaveform;
2889 Int_t nVsig=Vsig->GetSize();
2890
2891 if (nbits<=0 || nbits>60 || !range || fabs(Vbias)>fabs(range) || B<0 || (B && C<1))
2892 {
2893 printf("\n *%-s::ADC* Inconsistent input nbits=%-i range=%-g Vbias=%-g B=%-i C=%-i \n",ClassName(),nbits,range,Vbias,B,C);
2894 return arradc;
2895 }
2896
2897 NcMath math;
2898
2899 Long64_t N=pow(2,nbits); // The number of quantization levels
2900 Long64_t adcmin=0;
2901 Long64_t adcmax=N-1;
2902 Double_t Vref=0;
2903 Double_t Vfs=0;
2904 Double_t LSB=0;
2905
2906 // Floating point version of some parameters
2907 Double_t rN=N;
2908 Double_t rB=B;
2909 if (B==1) rB=exp(1);
2910 Double_t rC=C;
2911 Double_t radcmax=adcmax;
2912
2913 if (range<0) // |range| represents Vref
2914 {
2915 Vref=fabs(range);
2916 LSB=Vref/rN;
2917 Vfs=Vref-LSB;
2918 }
2919 else // range represents Vfs
2920 {
2921 Vfs=range;
2922 LSB=Vfs/radcmax;
2923 Vref=Vfs+LSB;
2924 }
2925
2926 Long64_t ped=0;
2927 Double_t frac=0;
2928 if (B) // Log ADC
2929 {
2930 if (range<0) Vfs=pow(rB,-rC)*pow(rB,radcmax*rC/rN)*Vref;
2931 if (range>0) Vref=pow(rB,rC)*pow(rB,-radcmax*rC/rN)*Vfs;
2932 LSB=Vref*pow(rB,-rC)*(pow(rB,rC/rN)-1.);
2933 frac=Vbias/Vref;
2934 ped=0;
2935 if (frac>0) ped=Long64_t(rN*(math.Log(rB,frac)+rC)/rC);
2936 }
2937
2938 if (LSB<=0 || Vfs<=0)
2939 {
2940 printf("\n *%-s::ADC* Inconsistent parameters : LSB=%-g Vfs=%-g \n",ClassName(),LSB,Vfs);
2941 return arradc;
2942 }
2943
2944 if (!B) ped=Vbias/LSB; // Pedestal value for a linear ADC
2945
2946 Double_t DR=20.*log10(Vfs/LSB);
2947
2948 TString mode="linear";
2949 if (B==1) mode="Log_e";
2950 if (B>1)
2951 {
2952 mode="Log_";
2953 mode+=B;
2954 }
2955
2956 if (!nVsig)
2957 {
2958 printf(" *%-s::ADC* No input data have been provided --> Only the value of adc(Vbias) is returned. \n",ClassName());
2959 if (!B)
2960 {
2961 printf(" Parameters for a %-i-bits %-s ADC with adc=[%-lli,%-lli] : \n",nbits,mode.Data(),adcmin,adcmax);
2962 printf(" Vref=%-g Vfs=%-g LSB=%-g DR=%-g (dB) Vbias=%-g adc(Vbias)=%-lli \n",Vref,Vfs,LSB,DR,Vbias,ped);
2963 }
2964 else
2965 {
2966 printf(" Parameters for a %-i-bits %-s ADC with adc=[%-lli,%-lli] and a code efficiency factor of %-i: \n",nbits,mode.Data(),adcmin,adcmax,C);
2967 printf(" Vref=%-g Vfs=%-g LSB=%-g DR=%-g (dB) Vbias=%-g adc(Vbias)=%-lli \n",Vref,Vfs,LSB,DR,Vbias,ped);
2968 }
2969 arradc.Set(1);
2970 arradc[0]=ped;
2971 return arradc;
2972 }
2973
2974 arradc.Set(nVsig);
2975
2976 if (hist)
2977 {
2978 TString title;
2979 if (fSample>0)
2980 {
2981 hist->SetBins(nVsig,0,double(nVsig)/fSample);
2982 title.Form("%-s %-i-bits %-s ADC with Vfs=%-g LSB=%-g (%-g samples/sec);Time in seconds;ADC counts",ClassName(),nbits,mode.Data(),Vfs,LSB,fSample);
2983 }
2984 else
2985 {
2986 title.Form("%-s %-i-bits %-s ADC with Vfs=%-g LSB=%-g;Sample number;ADC counts",ClassName(),nbits,mode.Data(),Vfs,LSB);
2987 hist->SetBins(nVsig,0,nVsig);
2988 }
2989 hist->SetMarkerStyle(20);
2990 hist->SetTitle(title);
2991 }
2992
2993 Double_t val=0;
2994 Double_t radcval=0;
2995 Long64_t adcval=0;
2996 for (Int_t j=0; j<nVsig; j++)
2997 {
2998 val=Vbias+Vsig->GetAt(j);
2999
3000 if (B) // Log ADC
3001 {
3002 radcval=0;
3003 frac=val/Vref;
3004 if (frac>0) radcval=(rN/rC)*(math.Log(rB,frac)+rC);
3005 }
3006 else // Linear ADC
3007 {
3008 radcval=val/LSB;
3009 }
3010
3011 adcval=Long64_t(radcval);
3012
3013 // Check for saturation
3014 if (adcval<adcmin) adcval=adcmin;
3015 if (adcval>adcmax) adcval=adcmax;
3016
3017 arradc[j]=adcval;
3018
3019 if (hist) hist->SetBinContent(j+1,adcval);
3020 }
3021
3022 return arradc;
3023}
3024
3025TArrayD NcDSP::DAC(Int_t nbits,Double_t range,Double_t Vbias,TArray* adcs,TArray* peds,TH1* hist,Int_t B,Int_t C) const
3026{
3114
3115 TArrayD arrdac(0);
3116 if (hist) hist->Reset();
3117
3118 if (!adcs) adcs=(TArray*)&fWaveform;
3119 Int_t nadcs=adcs->GetSize();
3120
3121 Int_t npeds=0;
3122 if (peds) npeds=peds->GetSize();
3123
3124 if (nbits<=0 || nbits>60 || !range || fabs(Vbias)>fabs(range) || (peds && npeds<nadcs) || B<0 || (B && C<1))
3125 {
3126 printf("\n *%-s::DAC* Inconsistent input nbits=%-i range=%-g Vbias=%-g nadcs=%-i npeds=%-i B=%-i C=%-i \n",ClassName(),nbits,range,Vbias,nadcs,npeds,B,C);
3127 return arrdac;
3128 }
3129
3130 NcMath math;
3131
3132 nbits=abs(nbits);
3133
3134 Long64_t N=pow(2,nbits); // The number of quantization levels
3135 Long64_t adcmin=0;
3136 Long64_t adcmax=N-1;
3137 Double_t Vref=0;
3138 Double_t Vfs=0;
3139 Double_t LSB=0;
3140
3141 // Floating point version of some parameters
3142 Double_t rN=N;
3143 Double_t rB=B;
3144 if (B==1) rB=exp(1);
3145 Double_t rC=C;
3146 Double_t radcmax=adcmax;
3147
3148 if (range<0) // |range| represents Vref
3149 {
3150 Vref=fabs(range);
3151 LSB=Vref/rN;
3152 Vfs=Vref-LSB;
3153 }
3154 else // range represents Vfs
3155 {
3156 Vfs=range;
3157 LSB=Vfs/radcmax;
3158 Vref=Vfs+LSB;
3159 }
3160
3161 Long64_t ped=0;
3162 Double_t frac=0;
3163 if (B) // Log DAC
3164 {
3165 if (range<0) Vfs=pow(rB,-rC)*pow(rB,radcmax*rC/rN)*Vref;
3166 if (range>0) Vref=pow(rB,rC)*pow(rB,-radcmax*rC/rN)*Vfs;
3167 LSB=Vref*pow(rB,-rC)*(pow(rB,rC/rN)-1.);
3168 frac=Vbias/Vref;
3169 ped=0;
3170 if (frac>0) ped=Long64_t(rN*(math.Log(rB,frac)+rC)/rC);
3171 }
3172
3173 if (LSB<=0 || Vfs<=0)
3174 {
3175 printf("\n *%-s::DAC* Inconsistent parameters : LSB=%-g Vfs=%-g \n",ClassName(),LSB,Vfs);
3176 return arrdac;
3177 }
3178
3179 if (!B) ped=Vbias/LSB; // Pedestal value for a linear DAC
3180
3181 Double_t DR=20.*log10(Vfs/LSB);
3182
3183 TString mode="linear";
3184 if (B==1) mode="Log_e";
3185 if (B>1)
3186 {
3187 mode="Log_";
3188 mode+=B;
3189 }
3190
3191 if (!nadcs)
3192 {
3193 printf(" *%-s::DAC* No input data have been provided --> Only the value of adc(Vbias) is returned. \n",ClassName());
3194 if (!B)
3195 {
3196 printf(" Parameters for a %-i-bits %-s DAC with adc=[%-lli,%-lli] : \n",nbits,mode.Data(),adcmin,adcmax);
3197 printf(" Vref=%-g Vfs=%-g LSB=%-g DR=%-g (dB) Vbias=%-g adc(Vbias)=%-lli \n",Vref,Vfs,LSB,DR,Vbias,ped);
3198 }
3199 else
3200 {
3201 printf(" Parameters for a %-i-bits %-s DAC with adc=[%-lli,%-lli] and a code efficiency factor of %-i: \n",nbits,mode.Data(),adcmin,adcmax,C);
3202 printf(" Vref=%-g Vfs=%-g LSB=%-g DR=%-g (dB) Vbias=%-g adc(Vbias)=%-lli \n",Vref,Vfs,LSB,DR,Vbias,ped);
3203 }
3204 arrdac.Set(1);
3205 arrdac[0]=ped;
3206 return arrdac;
3207 }
3208
3209 arrdac.Set(nadcs);
3210
3211 if (hist)
3212 {
3213 TString title;
3214 if (fSample>0)
3215 {
3216 hist->SetBins(nadcs,0,double(nadcs)/fSample);
3217 title.Form("%-s %-i-bits %-s DAC with Vfs=%-g LSB=%-g (%-g samples/sec);Time in seconds;Amplitude",ClassName(),nbits,mode.Data(),Vfs,LSB,fSample);
3218 }
3219 else
3220 {
3221 title.Form("%-s %-i-bits %-s DAC with Vfs=%-g LSB=%-g;Sample number;Amplitude",ClassName(),nbits,mode.Data(),Vfs,LSB);
3222 hist->SetBins(nadcs,0,nadcs);
3223 }
3224 hist->SetMarkerStyle(20);
3225 hist->SetTitle(title);
3226 }
3227
3228 Long64_t adc=0;
3229 Double_t radc=0;
3230 Double_t dacval=0;
3231 for (Int_t j=0; j<nadcs; j++)
3232 {
3233 adc=adcs->GetAt(j);
3234 radc=adc;
3235
3236 if (B) // Log DAC
3237 {
3238 dacval=Vref*pow(rB,-rC)*pow(rB,radc*rC/rN);
3239 }
3240 else // Linear DAC
3241 {
3242 if (peds)
3243 {
3244 ped=peds->GetAt(j);
3245 adc=adc-ped;
3246 radc=adc;
3247 }
3248 dacval=radc*LSB;
3249 }
3250
3251 // Correct for bias voltage
3252 if (B || (!B && !peds))
3253 {
3254 dacval=dacval-Vbias;
3255 }
3256
3257 arrdac[j]=dacval;
3258
3259 if (hist) hist->SetBinContent(j+1,dacval);
3260 }
3261
3262 return arrdac;
3263}
3264
3265TArrayD NcDSP::Transmit(Int_t nbits,Double_t range,Double_t Vbias,TArray* Vsig,TArray* peds,TH1* hist,Int_t B,Int_t C) const
3266{
3326
3327 TArrayL64 adcarr;
3328 TArrayD dacarr;
3329 if (hist) hist->Reset();
3330
3331 // Provide the ADC and DAC specs in case no input is provided
3332 if (!Vsig && fNwf<1)
3333 {
3334 printf(" *%-s::Transmit* Specifications for the ADC-DAC transmission chain. \n",ClassName());
3335 adcarr=ADC(nbits,range,Vbias,0,0,B,C);
3336 dacarr.Set(1);
3337 dacarr[0]=adcarr[0];
3338 return dacarr;
3339 }
3340
3341 // Perform the digitization via the ADC processeor
3342 adcarr=ADC(nbits,range,Vbias,Vsig,hist,B,C);
3343
3344 // Convert the digital data into analog signals via the DAC processor
3345 dacarr=DAC(nbits,range,Vbias,&adcarr,peds,hist,B,C);
3346
3347 if (hist)
3348 {
3349 TString title=hist->GetTitle();
3350 title.ReplaceAll("DAC","ADC-DAC (Transmit)");
3351 hist->SetTitle(title);
3352 }
3353
3354 return dacarr;
3355}
3356
3357TArrayD NcDSP::SampleAndHold(TF1 f,Double_t step,Double_t vmin,Double_t vmax,TH1* hist,Int_t loc) const
3358{
3378
3379 TArrayD data(0);
3380 if (hist) hist->Reset();
3381
3382 if (step<=0 || vmax<=vmin)
3383 {
3384 cout << " *" << ClassName() << "::SampleAndHold* Error : Invalid input step=" << step << " vmin=" << vmin << " vmax=" << vmax << endl;
3385 return data;
3386 }
3387
3388 // The number of samples
3389 Int_t n=(vmax-vmin)/step;
3390 data.Set(n);
3391
3392 if (hist)
3393 {
3394 hist->SetBins(n,vmin,vmax);
3395 TString sloc="start";
3396 if (!loc) sloc="center";
3397 if (loc>0) sloc="end";
3398 TString title;
3399 title.Form("NcDSP SampleAndHold for Function %-s in steps of %-.3g;X value;F(x) at the %-s of each step",(f.GetExpFormula("p")).Data(),step,sloc.Data());
3400 hist->SetTitle(title);
3401 hist->SetMarkerStyle(20);
3402 }
3403
3404 // Enter the sampled data into the output array
3405 Double_t xlow=vmin;
3406 Double_t xval=0;
3407 Double_t yval=0;
3408 Int_t i=0;
3409 while (xlow<=vmax)
3410 {
3411 if (i>=n) break;
3412
3413 if (loc<0) xval=xlow;
3414 if (!loc) xval=xlow+step/2.;
3415 if (loc>0) xval=xlow+step;
3416 if (xval>vmax) xval=vmax;
3417
3418 yval=f.Eval(xval);
3419 data[i]=yval;
3420
3421 if (hist) hist->SetBinContent(i+1,data[i]);
3422
3423 xlow+=step;
3424 i++;
3425 }
3426
3427 return data;
3428}
3429
3430TArrayD NcDSP::SampleAndHold(Int_t n,TH1* hist,Int_t loc,Int_t jmin,Int_t jmax) const
3431{
3455
3456 TArrayD data(0);
3457 if (hist) hist->Reset();
3458
3459 if (fNwf<1)
3460 {
3461 cout << " *" << ClassName() << "::SampleAndHold* Error : No waveform present." << endl;
3462 return data;
3463 }
3464
3465 if (jmax<=jmin)
3466 {
3467 jmin=0;
3468 jmax=fNwf-1;
3469 }
3470
3471 if (n<=0 || jmin<0 || jmin>=fNwf || jmax<0 || jmax>=fNwf)
3472 {
3473 cout << " *" << ClassName() << "::SampleAndHold* Invalid input n=" << n << " jmin=" << jmin << " jmax=" << jmax << endl;
3474 return data;
3475 }
3476
3477 // Fill the data array
3478 Int_t ndata=fNwf/n;
3479 if (fNwf%n) ndata++;
3480 data.Set(ndata);
3481 for (Int_t i=0; i<ndata; i++)
3482 {
3483 data[i]=0;
3484 }
3485
3486 Double_t val=0;
3487 Int_t j=0;
3488 Int_t k=0;
3489 for (Int_t i=0; i<ndata; i++)
3490 {
3491 if (j>jmax) break;
3492
3493 if (loc<0) k=j;
3494 if (!loc) k=j+n/2;
3495 if (loc>0) k=j+n;
3496
3497 if (k<jmin) continue;
3498
3499 if (k>jmax) k=jmax;
3500
3501 val=fWaveform[k];
3502 data[i]=val;
3503 j+=n;
3504 }
3505
3506 if (hist)
3507 {
3508 TString sloc="start";
3509 if (!loc) sloc="center";
3510 if (loc>0) sloc="end";
3511 TString title;
3512 if (fSample>0)
3513 {
3514 Double_t fnew=fSample/double(n);
3515 title.Form("NcDSP SampleAndHold over %-i original samplings (New: %-g samples/sec);Time in seconds;Value at the %-s of each new sample",n,fnew,sloc.Data());
3516 hist->SetBins(ndata,double(jmin)/fSample,double(jmax)/fSample);
3517 }
3518 else
3519 {
3520 title.Form("NcDSP SampleAndHold over %-i original samplings;New sample number;Value at the %-s of each new sample",n,sloc.Data());
3521 hist->SetBins(ndata,jmin,jmax);
3522 }
3523 hist->SetTitle(title);
3524 hist->SetMarkerStyle(20);
3525 for (Int_t i=1; i<=ndata; i++)
3526 {
3527 hist->SetBinContent(i,data[i-1]);
3528 }
3529 }
3530
3531 return data;
3532}
3533
3534TArrayD NcDSP::SampleAndSum(TF1 f,Double_t step,Double_t vmin,Double_t vmax,TH1* hist) const
3535{
3553
3554 TArrayD data(0);
3555 if (hist) hist->Reset();
3556
3557 if (step<=0 || vmax<=vmin)
3558 {
3559 cout << " *" << ClassName() << "::SampleAndSum* Error : Invalid input step=" << step << " vmin=" << vmin << " vmax=" << vmax << endl;
3560 return data;
3561 }
3562
3563 // The number of samples
3564 Int_t n=(vmax-vmin)/step;
3565 data.Set(n);
3566 for (Int_t i=0; i<n; i++)
3567 {
3568 data[i]=0;
3569 }
3570
3571 if (hist)
3572 {
3573 hist->SetBins(n,vmin,vmax);
3574 TString title;
3575 title.Form("NcDSP SampleAndSum for Function %-s with sampling steps of %-.3g;X value;Integral over each step",(f.GetExpFormula("p")).Data(),step);
3576 hist->SetTitle(title);
3577 hist->SetMarkerStyle(20);
3578 }
3579
3580 // Enter the sampled data into the output array
3581 Double_t xlow=vmin;
3582 Double_t xup=0;
3583 Double_t yval=0;
3584 Int_t i=0;
3585 while (xlow<=vmax)
3586 {
3587 if (i>=n) break;
3588
3589 xup=xlow+step;
3590 if (xup>vmax) xup=vmax;
3591
3592 yval=f.Integral(xlow,xup);
3593 data[i]=yval;
3594
3595 if (hist) hist->SetBinContent(i+1,data[i]);
3596
3597 xlow+=step;
3598 i++;
3599 }
3600
3601 return data;
3602}
3603
3604TArrayD NcDSP::SampleAndSum(Int_t n,TH1* hist,Int_t jmin,Int_t jmax) const
3605{
3627
3628 TArrayD data(0);
3629 if (hist) hist->Reset();
3630
3631 if (fNwf<1)
3632 {
3633 cout << " *" << ClassName() << "::SampleAndSum* Error : No waveform present." << endl;
3634 return data;
3635 }
3636
3637 if (jmax<=jmin)
3638 {
3639 jmin=0;
3640 jmax=fNwf-1;
3641 }
3642
3643 if (n<=0 || jmin<0 || jmin>=fNwf || jmax<0 || jmax>=fNwf)
3644 {
3645 cout << " *" << ClassName() << "::SampleAndSum* Invalid input n=" << n << " jmin=" << jmin << " jmax=" << jmax << endl;
3646 return data;
3647 }
3648
3649 // Fill the data array
3650 Int_t ndata=fNwf/n;
3651 if (fNwf%n) ndata++;
3652 data.Set(ndata);
3653 for (Int_t i=0; i<ndata; i++)
3654 {
3655 data[i]=0;
3656 }
3657
3658 Double_t sum=0;
3659 Int_t j=0;
3660 for (Int_t i=0; i<ndata; i++)
3661 {
3662 sum=0;
3663 for (Int_t k=0; k<n; k++)
3664 {
3665 if (j<jmin) continue;
3666 if (j>jmax) break;
3667 sum+=fWaveform[j];
3668 j++;
3669 }
3670 data[i]=sum;
3671 }
3672
3673 if (hist)
3674 {
3675 TString title;
3676 if (fSample>0)
3677 {
3678 Double_t fnew=fSample/double(n);
3679 title.Form("NcDSP SampleAndSum over %-i original samplings;Time in seconds;Summed value per %-.3g seconds",n,1./fnew);
3680 hist->SetBins(ndata,double(jmin)/fSample,double(jmax)/fSample);
3681 }
3682 else
3683 {
3684 title.Form("NcDSP SampleAndSum over %-i original samplings;New sample number;Summed value in each new sample",n);
3685 hist->SetBins(ndata,jmin,jmax);
3686 }
3687 hist->SetTitle(title);
3688 hist->SetMarkerStyle(20);
3689 for (Int_t i=1; i<=ndata; i++)
3690 {
3691 hist->SetBinContent(i,data[i-1]);
3692 }
3693 }
3694
3695 return data;
3696}
3697
3698TArrayD NcDSP::FilterMovingAverage(Int_t n,TString mode,TH1* hist,Int_t* i1,Int_t* i2,TH1* hisf,Bool_t dB)
3699{
3789
3790 Int_t ny=0;
3791 TArrayD y(ny);
3792 if (hist) hist->Reset();
3793 if (hisf) hisf->Reset();
3794 Int_t nx=fReIn.GetSize();
3795
3796 if (nx<1)
3797 {
3798 printf(" *%-s::FilterMovingAverage* No loaded input data present. \n",ClassName());
3799 return y;
3800 }
3801
3802 if (n<1 || n>nx || (mode!="rec" && mode!="conv"))
3803 {
3804 printf(" *%-s::FilterMovingAverage* Inconsistent input n=%-i for x[%-i] and mode=%-s \n",ClassName(),n,nx,mode.Data());
3805 return y;
3806 }
3807
3808 // Save the current stored data
3809 TArrayD xsave=fReIn;
3810 TArrayD wfsave=fWaveform;
3811
3812 if (mode=="conv") // Convolution mode
3813 {
3814 // The filter kernel
3815 TArrayD h=GetMovingAverageKernel(n);
3816 SetWaveform(&h);
3817
3818 // Perform the convolution
3819 y=Convolve(hist,i1,i2);
3820 }
3821 else // Recursive mode
3822 {
3823 TArrayD x=fReIn;
3824 ny=nx-n+1;
3825 if (i1 || i2) ny=nx;
3826
3827 if (i1) *i1=0;
3828 if (i2) *i2=nx-n;
3829
3830 y.Set(ny);
3831 y.Reset();
3832
3833 // Calculate the first y-value summation
3834 for (Int_t i=0; i<n; i++)
3835 {
3836 y[0]+=x[i];
3837 }
3838
3839 // The recursive summation
3840 Double_t add=0;
3841 for (Int_t k=1; k<ny; k++)
3842 {
3843 add=0;
3844 if ((k+n-1)<nx) add=x[k+n-1];
3845 y[k]=y[k-1]-x[k-1]+add;
3846 }
3847
3848 Double_t rn=n;
3849 // Calculate the average values
3850 for (Int_t i=0; i<ny; i++)
3851 {
3852 y[i]=y[i]/rn;
3853 }
3854 }
3855
3856 TString title;
3857 if (hist)
3858 {
3859 if (mode=="rec")
3860 {
3861 if (fSample>0)
3862 {
3863 title.Form("%-s;Time in seconds;Value",ClassName());
3864 hist->SetBins(ny,0,double(ny)/fSample);
3865 }
3866 else
3867 {
3868 title.Form("%-s;Sample number;Value",ClassName());
3869 hist->SetBins(ny,0,ny);
3870 }
3871
3872 // Set histogram axis labels and provisonal title
3873 hist->SetTitle(title);
3874
3875 // Fill the histogram
3876 for (Int_t ibin=1; ibin<=ny; ibin++)
3877 {
3878 hist->SetBinContent(ibin,y[ibin-1]);
3879 }
3880
3881 // Indicate the values of i1 and i2 (if requested) by vertical blue dashed lines
3882 if (i1 || i2)
3883 {
3884 Double_t ymin=hist->GetMinimum();
3885 Double_t ymax=hist->GetMaximum();
3886
3887 Double_t xlow=0;
3888 Double_t xup=0;
3889 if (i1) xlow=hist->GetBinLowEdge(*i1+1);
3890 if (i2)
3891 {
3892 xup=hist->GetBinLowEdge(*i2+1);
3893 xup+=hist->GetBinWidth(1);
3894 }
3895
3896 TLine* vline1=0;
3897 TLine* vline2=0;
3898
3899 if (i1)
3900 {
3901 vline1=new TLine(xlow,ymin,xlow,ymax);
3902 vline1->SetLineStyle(2); // Dashed line
3903 vline1->SetLineWidth(2);
3904 vline1->SetLineColor(4); // Blue color
3905 }
3906 if (i2)
3907 {
3908 vline2=new TLine(xup,ymin,xup,ymax);
3909 vline2->SetLineStyle(2); // Dashed line
3910 vline2->SetLineWidth(2);
3911 vline2->SetLineColor(4); // Blue color
3912 }
3913
3914 TList* hlist=hist->GetListOfFunctions();
3915 if (vline1) hlist->Add(vline1);
3916 if (vline2) hlist->Add(vline2);
3917 }
3918 }
3919
3920 // Set the appropriate histogram title
3921 title.Form("%-s Moving Average (%-s mode) Filter: Time domain result averaged over %-i samples",ClassName(),mode.Data(),n);
3922 hist->SetTitle(title);
3923 }
3924
3925 // Fill the filtered frequency domain histogram
3926 if (hisf)
3927 {
3928 // Obtain the frequency domain histogram
3929 HistogramFilterFFT(&y,hisf,dB,kFALSE);
3930
3931 // Set the appropriate histogram title
3932 title.Form("%-s Moving Average (%-s mode) Filter: Frequency domain result (%-i sample averaging in time domain)",ClassName(),mode.Data(),n);
3933 hisf->SetTitle(title);
3934 }
3935
3936 // Restore the original input data
3937 Load(&xsave);
3938 SetWaveform(&wfsave);
3939
3940 // Let user invokations of Load() reset the output data again
3941 fKeepOutput=kFALSE;
3942
3943 return y;
3944}
3945
3946TArrayD NcDSP::FilterLowPass(Double_t fcut,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Int_t* i1,Int_t* i2,Bool_t adaptn)
3947{
4012
4013 TArrayD y(0);
4014 if (hisf) hisf->Reset();
4015 if (hist) hist->Reset();
4016 Int_t nx=fReIn.GetSize();
4017
4018 if (nx<1)
4019 {
4020 printf(" *%-s::FilterLowPass* No loaded input data present. \n",ClassName());
4021 return y;
4022 }
4023
4024 if (n<1 || fcut<=0 || fcut>0.5)
4025 {
4026 printf(" *%-s::FilterLowPass* Invalid input fcut=%-g n=%-i \n",ClassName(),fcut,n);
4027 return y;
4028 }
4029
4030 // Save the current stored data
4031 TArrayD xsave=fReIn;
4032 TArrayD wfsave=fWaveform;
4033
4034 // Adapt "n" to an odd value if needed
4035 Int_t odd=n%2;
4036 if (!odd && adaptn) n++;
4037
4038 // The filter kernel
4039 TArrayD h=GetLowPassKernel(fcut,n,0,0,0,adaptn);
4040
4041 // Perform the convolution
4042 SetWaveform(&h);
4043 y=Convolve(hist,i1,i2,2);
4044
4045 // Set title for the filtered time domain histogram
4046 if (hist)
4047 {
4048 TString title;
4049 if (fSample>0)
4050 {
4051 Float_t nucut=fcut*fSample;
4052 title.Form("%-s Low Pass Filter: Time domain result with #nu-cut=%-.3g Hz (%-i-point kernel)",ClassName(),nucut,n);
4053 }
4054 else
4055 {
4056 title.Form("%-s Low Pass Filter: Time domain result with #nu-cut/#nu-sample=%-.3g (%-i-point kernel)",ClassName(),fcut,n);
4057 }
4058 hist->SetTitle(title);
4059 }
4060
4061 // Fill the filtered frequency domain histogram
4062 if (hisf)
4063 {
4064 // Obtain the frequency domain histogram
4065 HistogramFilterFFT(&y,hisf,dB,kFALSE);
4066
4067 // Set the appropriate histogram title
4068 TString title;
4069 if (fSample>0)
4070 {
4071 Float_t nucut=fcut*fSample;
4072 title.Form("%-s Low Pass Filter: Frequency domain result with #nu-cut=%-.3g Hz (%-i-point time domain kernel)",ClassName(),nucut,n);
4073 }
4074 else
4075 {
4076 title.Form("%-s Low Pass Filter: Frequency domain result with #nu-cut/#nu-sample=%-.3g (%-i-point time domain kernel)",ClassName(),fcut,n);
4077 }
4078 hisf->SetTitle(title);
4079 }
4080
4081 // Restore the original input data
4082 Load(&xsave);
4083 SetWaveform(&wfsave);
4084
4085 // Let user invokations of Load() reset the output data again
4086 fKeepOutput=kFALSE;
4087
4088 return y;
4089}
4090
4091TArrayD NcDSP::FilterHighPass(Double_t fcut,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Int_t* i1,Int_t* i2,Bool_t adaptn)
4092{
4157
4158 TArrayD y(0);
4159 if (hisf) hisf->Reset();
4160 if (hist) hist->Reset();
4161 Int_t nx=fReIn.GetSize();
4162
4163 if (nx<1)
4164 {
4165 printf(" *%-s::FilterHighPass* No loaded input data present. \n",ClassName());
4166 return y;
4167 }
4168
4169 if (n<1 || fcut<=0 || fcut>0.5)
4170 {
4171 printf(" *%-s::FilterHighPass* Invalid input fcut=%-g n=%-i \n",ClassName(),fcut,n);
4172 return y;
4173 }
4174
4175 // Save the current stored data
4176 TArrayD xsave=fReIn;
4177 TArrayD wfsave=fWaveform;
4178
4179 // Adapt "n" to an odd value if needed
4180 Int_t odd=n%2;
4181 if (!odd && adaptn) n++;
4182
4183 // The filter kernel
4184 TArrayD h=GetHighPassKernel(fcut,n,0,0,0,adaptn);
4185
4186 // Perform the convolution
4187 SetWaveform(&h);
4188 y=Convolve(hist,i1,i2,2);
4189
4190 // Set title for the filtered time domain histogram
4191 if (hist)
4192 {
4193 TString title;
4194 if (fSample>0)
4195 {
4196 Float_t nucut=fcut*fSample;
4197 title.Form("NcDSP High Pass Filter: Time domain result with #nu-cut=%-.3g Hz (%-i-point kernel)",nucut,n);
4198 }
4199 else
4200 {
4201 title.Form("NcDSP High Pass Filter: Time domain result with #nu-cut/#nu-sample=%-.3g (%-i-point kernel)",fcut,n);
4202 }
4203 hist->SetTitle(title);
4204 }
4205
4206 // Fill the filtered frequency domain histogram
4207 if (hisf)
4208 {
4209 // Obtain the frequency domain histogram
4210 HistogramFilterFFT(&y,hisf,dB,kFALSE);
4211
4212 // Set the appropriate histogram title
4213 TString title;
4214 if (fSample>0)
4215 {
4216 Float_t nucut=fcut*fSample;
4217 title.Form("NcDSP High Pass Filter: Frequency domain result with #nu-cut=%-.3g Hz (%-i-point time domain kernel)",nucut,n);
4218 }
4219 else
4220 {
4221 title.Form("NcDSP High Pass Filter: Frequency domain result with #nu-cut/#nu-sample=%-.3g (%-i-point time domain kernel)",fcut,n);
4222 }
4223 hisf->SetTitle(title);
4224 }
4225
4226 // Restore the original input data
4227 Load(&xsave);
4228 SetWaveform(&wfsave);
4229
4230 // Let user invokations of Load() reset the output data again
4231 fKeepOutput=kFALSE;
4232
4233 return y;
4234}
4235
4236TArrayD NcDSP::FilterBandPass(Double_t f1,Double_t f2,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Int_t* i1,Int_t* i2,Bool_t adaptn)
4237{
4304
4305 TArrayD y(0);
4306 if (hisf) hisf->Reset();
4307 if (hist) hist->Reset();
4308 Int_t nx=fReIn.GetSize();
4309
4310 if (nx<1)
4311 {
4312 printf(" *%-s::FilterBandPass* No loaded input data present. \n",ClassName());
4313 return y;
4314 }
4315
4316 if (n<1 || f1<=0 || f1>0.5 || f2<=0 || f2>0.5 || f2<=f1)
4317 {
4318 printf(" *%-s::FilterBandPass* Invalid input f1=%-g f2=%-g n=%-i \n",ClassName(),f1,f2,n);
4319 return y;
4320 }
4321
4322 // Save the current stored data
4323 TArrayD xsave=fReIn;
4324 TArrayD wfsave=fWaveform;
4325
4326 // Adapt "n" to an odd value if needed
4327 Int_t odd=n%2;
4328 if (!odd && adaptn) n++;
4329
4330 // The filter kernel
4331 TArrayD h=GetBandPassKernel(f1,f2,n,0,0,0,adaptn);
4332
4333 // Perform the convolution
4334 SetWaveform(&h);
4335 y=Convolve(hist,i1,i2,2);
4336
4337 // Set title for the filtered time domain histogram
4338 if (hist)
4339 {
4340 TString title;
4341 if (fSample>0)
4342 {
4343 Float_t nu1=f1*fSample;
4344 Float_t nu2=f2*fSample;
4345 title.Form("NcDSP Band Pass Filter: Time domain result for [%-.3g,%-.3g] Hz (%-i-point kernel)",nu1,nu2,n);
4346 }
4347 else
4348 {
4349 title.Form("NcDSP Band Pass Filter: Time domain result for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point kernel)",f1,f2,n);
4350 }
4351 hist->SetTitle(title);
4352 }
4353
4354 // Fill the filtered frequency domain histogram
4355 if (hisf)
4356 {
4357 // Obtain the frequency domain histogram
4358 HistogramFilterFFT(&y,hisf,dB,kFALSE);
4359
4360 // Set the appropriate histogram title
4361 TString title;
4362 if (fSample>0)
4363 {
4364 Float_t nu1=f1*fSample;
4365 Float_t nu2=f2*fSample;
4366 title.Form("NcDSP Band Pass Filter: Frequency domain result for [%-.3g,%-.3g] Hz (%-i-point time domain kernel)",nu1,nu2,n);
4367 }
4368 else
4369 {
4370 title.Form("NcDSP Band Pass Filter: Frequency domain result for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point time domain kernel)",f1,f2,n);
4371 }
4372 hisf->SetTitle(title);
4373 }
4374
4375 // Restore the original input data
4376 Load(&xsave);
4377 SetWaveform(&wfsave);
4378
4379 // Let user invokations of Load() reset the output data again
4380 fKeepOutput=kFALSE;
4381
4382 return y;
4383}
4384
4385TArrayD NcDSP::FilterBandReject(Double_t f1,Double_t f2,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Int_t* i1,Int_t* i2,Bool_t adaptn)
4386{
4452
4453 TArrayD y(0);
4454 if (hisf) hisf->Reset();
4455 if (hist) hist->Reset();
4456 Int_t nx=fReIn.GetSize();
4457
4458 if (nx<1)
4459 {
4460 printf(" *%-s::FilterBandReject* No loaded input data present. \n",ClassName());
4461 return y;
4462 }
4463
4464 if (n<1 || f1<=0 || f1>0.5 || f2<=0 || f2>0.5 || f2<=f1)
4465 {
4466 printf(" *%-s::FilterBandReject* Invalid input f1=%-g f2=%-g n=%-i \n",ClassName(),f1,f2,n);
4467 return y;
4468 }
4469
4470 // Save the current stored data
4471 TArrayD xsave=fReIn;
4472 TArrayD wfsave=fWaveform;
4473
4474 // Adapt "n" to an odd value if needed
4475 Int_t odd=n%2;
4476 if (!odd && adaptn) n++;
4477
4478 // The filter kernel
4479 TArrayD h=GetBandRejectKernel(f1,f2,n,0,0,0,adaptn);
4480
4481 // Perform the convolution
4482 SetWaveform(&h);
4483 y=Convolve(hist,i1,i2,2);
4484
4485 // Set title for the filtered time domain histogram
4486 if (hist)
4487 {
4488 TString title;
4489 if (fSample>0)
4490 {
4491 Float_t nu1=f1*fSample;
4492 Float_t nu2=f2*fSample;
4493 title.Form("NcDSP Band Reject Filter: Time domain result for [%-.3g,%-.3g] Hz (%-i-point kernel)",nu1,nu2,n);
4494 }
4495 else
4496 {
4497 title.Form("NcDSP Band Reject Filter: Time domain result for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point kernel)",f1,f2,n);
4498 }
4499 hist->SetTitle(title);
4500 }
4501
4502 // Fill the filtered frequency domain histogram
4503 if (hisf)
4504 {
4505 // Obtain the frequency domain histogram
4506 HistogramFilterFFT(&y,hisf,dB,kFALSE);
4507
4508 // Set the appropriate histogram title
4509 TString title;
4510 if (fSample>0)
4511 {
4512 Float_t nu1=f1*fSample;
4513 Float_t nu2=f2*fSample;
4514 title.Form("NcDSP Band Reject Filter: Frequency domain result for [%-.3g,%-.3g] Hz (%-i-point time domain kernel)",nu1,nu2,n);
4515 }
4516 else
4517 {
4518 title.Form("NcDSP Band Reject Filter: Frequency domain result for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point time domain kernel)",f1,f2,n);
4519 }
4520 hisf->SetTitle(title);
4521 }
4522
4523 // Restore the original input data
4524 Load(&xsave);
4525 SetWaveform(&wfsave);
4526
4527 // Let user invokations of Load() reset the output data again
4528 fKeepOutput=kFALSE;
4529
4530 return y;
4531}
4532
4533TArrayD NcDSP::FilterMultiBand(TArray& freqs,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Int_t* i1,Int_t* i2,Bool_t adaptn)
4534{
4604
4605 TArrayD y(0);
4606 if (hisf) hisf->Reset();
4607 if (hist) hist->Reset();
4608 Int_t nx=fReIn.GetSize();
4609
4610 if (nx<1)
4611 {
4612 printf(" *%-s::FilterMultiBand* No loaded input data present. \n",ClassName());
4613 return y;
4614 }
4615
4616 Int_t arrsize=freqs.GetSize();
4617 Int_t oddsize=arrsize%2;
4618 Int_t nbands=arrsize/2;
4619 if (nbands<1 || n<1 || oddsize)
4620 {
4621 printf(" *%-s::FilterMultiBand* Invalid input array size=%-i nbands=%-i n=%-i \n",ClassName(),arrsize,nbands,n);
4622 return y;
4623 }
4624
4625 // Save the current stored data
4626 TArrayD xsave=fReIn;
4627 TArrayD wfsave=fWaveform;
4628
4629 // Adapt "n" to an odd value if needed
4630 Int_t odd=n%2;
4631 if (!odd && adaptn) n++;
4632
4633 // The filter kernel
4634 TArrayD h=GetMultiBandKernel(freqs,n,0,0,0,adaptn);
4635
4636 // Convolve the composite kernel with the original time domain data
4637 Load(&xsave);
4638 SetWaveform(&h);
4639 y=Convolve(hist,i1,i2,2);
4640
4641 // Determine the number of actually specified bands
4642 Double_t flow=0;
4643 Double_t fup=0;
4644 Int_t index=0;
4645 Int_t neff=0; // The number of off actually specified bands
4646 // Loop over the specified frequency bands
4647 for (Int_t jband=1; jband<=nbands; jband++)
4648 {
4649 index=2*(jband-1);
4650 flow=freqs.GetAt(index);
4651 fup=freqs.GetAt(index+1);
4652
4653 // Skip empty entries in the "freqs" array
4654 if (!flow || !fup) continue;
4655
4656 neff++;
4657 }
4658
4659 TString title;
4660 // Set title for the filtered time domain histogram
4661 if (hist)
4662 {
4663 title.Form("%-s MultiBand Filter: Time domain result for %-i bands (%-i-point kernel each)",ClassName(),neff,n);
4664 hist->SetTitle(title);
4665 }
4666
4667 // Fill the filtered frequency domain histogram
4668 if (hisf)
4669 {
4670 // Obtain the frequency domain histogram
4671 HistogramFilterFFT(&y,hisf,dB,kFALSE);
4672
4673 // Set the appropriate histogram title
4674 title.Form("%-s MultiBand Filter: Frequency domain result for %-i bands (%-i-point time domain kernel each)",ClassName(),neff,n);
4675 hisf->SetTitle(title);
4676 }
4677
4678 // Restore the original input data
4679 Load(&xsave);
4680 SetWaveform(&wfsave);
4681
4682 // Let user invokations of Load() reset the output data again
4683 fKeepOutput=kFALSE;
4684
4685 return y;
4686}
4687
4688TArrayD NcDSP::GetMovingAverageKernel(Int_t n,TH1* hisf,Bool_t dB,TH1* hist)
4689{
4729
4730 TArrayD h(0);
4731 if (hisf) hisf->Reset();
4732 if (hist) hist->Reset();
4733
4734 if (n<1)
4735 {
4736 printf(" *%-s::GetMovingAverageKernel* Invalid input n=%-i \n",ClassName(),n);
4737 return h;
4738 }
4739
4740 // Save the current stored data
4741 TArrayD xsave=fReIn;
4742 TArrayD wfsave=fWaveform;
4743
4744 h.Set(n);
4745 for (Int_t i=0; i<n; i++)
4746 {
4747 h[i]=1./double(n);
4748 }
4749
4750 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
4751
4752 // Set the appropriate histogram titles
4753 TString title;
4754 if (hisf)
4755 {
4756 title.Form("NcDSP Moving Average Filter: Frequency domain kernel (%-i-point time domain kernel)",n);
4757 hisf->SetTitle(title);
4758 }
4759
4760 if (hist)
4761 {
4762 title.Form("NcDSP Moving Average Filter: Time domain kernel (%-i-point zero padded)",n);
4763 hist->SetTitle(title);
4764 }
4765
4766 // Restore the original input data
4767 Load(&xsave);
4768 SetWaveform(&wfsave);
4769
4770 // Let user invokations of Load() reset the output data again
4771 fKeepOutput=kFALSE;
4772
4773 return h;
4774}
4775
4776TArrayD NcDSP::GetLowPassKernel(Double_t fcut,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Bool_t adaptn)
4777{
4825
4826 TArrayD h(0);
4827 if (hisf) hisf->Reset();
4828
4829 if (n<1 || fcut<=0 || fcut>0.5)
4830 {
4831 printf(" *%-s::GetLowPassKernel* Invalid input fcut=%-g n=%-i \n",ClassName(),fcut,n);
4832 return h;
4833 }
4834
4835 // Save the current stored data
4836 TArrayD xsave=fReIn;
4837 TArrayD wfsave=fWaveform;
4838
4839 // Adapt "n" to an odd value if needed
4840 Int_t odd=n%2;
4841 if (!odd && adaptn) n++;
4842
4843 Double_t twopi=2.*acos(-1.);
4844 h.Set(n);
4845 Int_t m=n-1;
4846 Double_t rm=m;
4847 Double_t ri=0;
4848 Double_t sum=0;
4849 for (Int_t i=0; i<=m; i++)
4850 {
4851 if (i==m/2)
4852 {
4853 h[i]=twopi*fcut;
4854 }
4855 else
4856 {
4857 ri=i;
4858 h[i]=sin(twopi*fcut*double(i-m/2))*(0.42-0.5*cos(twopi*ri/rm)+0.08*cos(2.*twopi*ri/rm))/double(i-m/2);
4859 }
4860 sum+=h[i];
4861 }
4862
4863 // Normalize the filter kernel to 1
4864 for (Int_t i=0; i<n; i++)
4865 {
4866 h[i]=h[i]/sum;
4867 }
4868
4869 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
4870
4871 // Set the appropriate histogram titles
4872 TString title;
4873 if (hisf)
4874 {
4875 if (fSample>0)
4876 {
4877 Float_t nucut=fcut*fSample;
4878 title.Form("NcDSP Low Pass Filter: Frequency domain kernel with #nu-cut=%-.3g Hz (%-i-point time domain kernel)",nucut,n);
4879 }
4880 else
4881 {
4882 title.Form("NcDSP Low Pass Filter: Frequency domain kernel with #nu-cut/#nu-sample=%-.3g (%-i-point time domain kenel)",fcut,n);
4883 }
4884 hisf->SetTitle(title);
4885 }
4886
4887 if (hist)
4888 {
4889 if (fSample>0)
4890 {
4891 Float_t nucut=fcut*fSample;
4892 title.Form("NcDSP Low Pass Filter: Time domain kernel (%-i-point zero padded) with #nu-cut=%-.3g Hz",n,nucut);
4893 }
4894 else
4895 {
4896 title.Form("NcDSP Low Pass Filter: Time domain kernel (%-i-point zero padded) with #nu-cut/#nu-sample=%-.3g",n,fcut);
4897 }
4898 hist->SetTitle(title);
4899 }
4900
4901 // Restore the original input data
4902 Load(&xsave);
4903 SetWaveform(&wfsave);
4904
4905 // Let user invokations of Load() reset the output data again
4906 fKeepOutput=kFALSE;
4907
4908 return h;
4909}
4910
4911TArrayD NcDSP::GetHighPassKernel(Double_t fcut,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Bool_t adaptn)
4912{
4960
4961 TArrayD h(0);
4962 if (hisf) hisf->Reset();
4963
4964 if (n<1 || fcut<=0 || fcut>0.5)
4965 {
4966 printf(" *%-s::GetHighPassKernel* Invalid input fcut=%-g n=%-i \n",ClassName(),fcut,n);
4967 return h;
4968 }
4969
4970 // Save the current stored data
4971 TArrayD xsave=fReIn;
4972 TArrayD wfsave=fWaveform;
4973
4974 // Adapt "n" to an odd value if needed
4975 Int_t odd=n%2;
4976 if (!odd && adaptn) n++;
4977
4978 // The corresponding Low Pass filter kernel
4979 h=GetLowPassKernel(fcut,n,0,0,0,adaptn);
4980
4981 // Spectrally invert the filter kernel to obtain the High Pass kernel
4982 for (Int_t i=0; i<n; i++)
4983 {
4984 h[i]=-h[i];
4985 }
4986 h[n/2]=h[n/2]+1.;
4987
4988 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
4989
4990 // Set the appropriate histogram title
4991 TString title;
4992 if (hisf)
4993 {
4994 if (fSample>0)
4995 {
4996 Float_t nucut=fcut*fSample;
4997 title.Form("NcDSP High Pass Filter: Frequency domain kernel with #nu-cut=%-.3g Hz (%-i-point time domain kernel)",nucut,n);
4998 }
4999 else
5000 {
5001 title.Form("NcDSP High Pass Filter: Frequency domain kernel with #nu-cut/#nu-sample=%-.3g (%-i-point time domain kernel)",fcut,n);
5002 }
5003 hisf->SetTitle(title);
5004 }
5005
5006 if (hist)
5007 {
5008 if (fSample>0)
5009 {
5010 Float_t nucut=fcut*fSample;
5011 title.Form("NcDSP High Pass Filter: Time domain kernel (%-i-point zero padded) with #nu-cut=%-.3g Hz",n,nucut);
5012 }
5013 else
5014 {
5015 title.Form("NcDSP High Pass Filter: Time domain kernel (%-i-point zero padded) with #nu-cut/#nu-sample=%-.3g",n,fcut);
5016 }
5017 hist->SetTitle(title);
5018 }
5019
5020 // Restore the original input data
5021 Load(&xsave);
5022 SetWaveform(&wfsave);
5023
5024 // Let user invokations of Load() reset the output data again
5025 fKeepOutput=kFALSE;
5026
5027 return h;
5028}
5029
5030TArrayD NcDSP::GetBandPassKernel(Double_t f1,Double_t f2,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Bool_t adaptn)
5031{
5081
5082 TArrayD h(0);
5083 if (hisf) hisf->Reset();
5084
5085 if (n<1 || f1<=0 || f1>0.5 || f2<=0 || f2>0.5 || f2<=f1)
5086 {
5087 printf(" *%-s::GetBandPassKernel* Invalid input f1=%-g f2=%-g n=%-i \n",ClassName(),f1,f2,n);
5088 return h;
5089 }
5090
5091 // Save the current stored data
5092 TArrayD xsave=fReIn;
5093 TArrayD wfsave=fWaveform;
5094
5095 // Adapt "n" to an odd value if needed
5096 Int_t odd=n%2;
5097 if (!odd && adaptn) n++;
5098
5099 // Get the corresponding Band Reject kernel
5100 h=GetBandRejectKernel(f1,f2,n,0,0,0,adaptn);
5101
5102 // Spectrally invert the Band Reject filter kernel to obtain the Band Pass kernel
5103 for (Int_t i=0; i<n; i++)
5104 {
5105 h[i]=-h[i];
5106 }
5107 h[n/2]=h[n/2]+1.;
5108
5109 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
5110
5111 // Set the appropriate histogram title
5112 TString title;
5113 if (hisf)
5114 {
5115 if (fSample>0)
5116 {
5117 Float_t nu1=f1*fSample;
5118 Float_t nu2=f2*fSample;
5119 title.Form("NcDSP Band Pass Filter: Frequency domain kernel for [%-.3g,%-.3g] Hz (%-i-point time domain kernel)",nu1,nu2,n);
5120 }
5121 else
5122 {
5123 title.Form("NcDSP Band Pass Filter: Frequency domain kernel for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point time domain kernel)",f1,f2,n);
5124 }
5125 hisf->SetTitle(title);
5126 }
5127
5128 if (hist)
5129 {
5130 if (fSample>0)
5131 {
5132 Float_t nu1=f1*fSample;
5133 Float_t nu2=f2*fSample;
5134 title.Form("NcDSP Band Pass Filter: Time domain kernel (%-i-point zero padded) for [%-.3g,%-.3g] Hz",n,nu1,nu2);
5135 }
5136 else
5137 {
5138 title.Form("NcDSP Band Pass Filter: Time domain kernel (%-i-point zero padded) for #nu/#nu-sample=[%-.3g,%-.3g]",n,f1,f2);
5139 }
5140 hist->SetTitle(title);
5141 }
5142
5143 // Restore the original input data
5144 Load(&xsave);
5145 SetWaveform(&wfsave);
5146
5147 // Let user invokations of Load() reset the output data again
5148 fKeepOutput=kFALSE;
5149
5150 return h;
5151}
5152
5153TArrayD NcDSP::GetBandRejectKernel(Double_t f1,Double_t f2,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Bool_t adaptn)
5154{
5203
5204 TArrayD h(0);
5205 if (hisf) hisf->Reset();
5206
5207 if (n<1 || f1<=0 || f1>0.5 || f2<=0 || f2>0.5 || f2<=f1)
5208 {
5209 printf(" *%-s::GetBandRejectKernel* Invalid input f1=%-g f2=%-g n=%-i \n",ClassName(),f1,f2,n);
5210 return h;
5211 }
5212
5213 // Save the current stored data
5214 TArrayD xsave=fReIn;
5215 TArrayD wfsave=fWaveform;
5216
5217 // Adapt "n" to an odd value if needed
5218 Int_t odd=n%2;
5219 if (!odd && adaptn) n++;
5220
5221 // The Low Pass filter kernel for f1
5222 TArrayD hlow=GetLowPassKernel(f1,n,0,0,0,adaptn);
5223
5224 // The High Pass filter kernel for f2
5225 TArrayD hhigh=GetHighPassKernel(f2,n,0,0,0,adaptn);
5226
5227 // Add the Low Pass and High Pass kernels to obtain a Band Reject kernel
5228 h.Set(n);
5229 for (Int_t i=0; i<n; i++)
5230 {
5231 h[i]=hlow[i]+hhigh[i];
5232 }
5233
5234 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
5235
5236 // Set the appropriate histogram title
5237 TString title;
5238 if (hisf)
5239 {
5240 if (fSample>0)
5241 {
5242 Float_t nu1=f1*fSample;
5243 Float_t nu2=f2*fSample;
5244 title.Form("NcDSP Band Reject Filter: Frequency domain kernel for [%-.3g,%-.3g] Hz (%-i-point time domain kernel)",nu1,nu2,n);
5245 }
5246 else
5247 {
5248 title.Form("NcDSP Band Reject Filter: Frequency domain kernel for #nu/#nu-sample=[%-.3g,%-.3g] (%-i-point time domain kernel)",f1,f2,n);
5249 }
5250 hisf->SetTitle(title);
5251 }
5252
5253 if (hist)
5254 {
5255 if (fSample>0)
5256 {
5257 Float_t nu1=f1*fSample;
5258 Float_t nu2=f2*fSample;
5259 title.Form("NcDSP Band Reject Filter: Time domain kernel (%-i-point zero padded) for [%-.3g,%-.3g] Hz",n,nu1,nu2);
5260 }
5261 else
5262 {
5263 title.Form("NcDSP Band Reject Filter: Time domain kernel (%-i-point zero padded) for #nu/#nu-sample=[%-.3g,%-.3g]",n,f1,f2);
5264 }
5265 hist->SetTitle(title);
5266 }
5267
5268 // Restore the original input data
5269 Load(&xsave);
5270 SetWaveform(&wfsave);
5271
5272 // Let user invokations of Load() reset the output data again
5273 fKeepOutput=kFALSE;
5274
5275 return h;
5276}
5277
5278TArrayD NcDSP::GetMultiBandKernel(TArray& freqs,Int_t n,TH1* hisf,Bool_t dB,TH1* hist,Bool_t adaptn)
5279{
5333
5334 TArrayD h(0); // The convolution of the various filter kernels
5335 if (hisf) hisf->Reset();
5336
5337 Int_t arrsize=freqs.GetSize();
5338 Int_t oddsize=arrsize%2;
5339 Int_t nbands=arrsize/2;
5340 if (nbands<1 || n<1 || oddsize)
5341 {
5342 printf(" *%-s::GetMultiBandKernel* Invalid input array size=%-i nbands=%-i n=%-i \n",ClassName(),arrsize,nbands,n);
5343 return h;
5344 }
5345
5346 // Save the current stored data
5347 TArrayD xsave=fReIn;
5348 TArrayD wfsave=fWaveform;
5349
5350 // Adapt "n" to an odd value if needed
5351 Int_t odd=n%2;
5352 if (!odd && adaptn) n++;
5353
5354 Double_t flow=0;
5355 Double_t fup=0;
5356 Int_t index=0;
5357 TArrayD hj; // The filter kernel for a single band
5358 Bool_t first=kTRUE;
5359 Int_t neff=0; // The number of off actually specified bands
5360 // Loop over the specified frequency bands
5361 for (Int_t jband=1; jband<=nbands; jband++)
5362 {
5363 index=2*(jband-1);
5364 flow=freqs.GetAt(index);
5365 fup=freqs.GetAt(index+1);
5366
5367 // Skip empty entries in the "freqs" array
5368 if (!flow || !fup) continue;
5369
5370 neff++;
5371
5372 if (flow>0 && fup>0) hj=GetBandPassKernel(flow,fup,n,0,0,0,adaptn);
5373
5374 if (flow<0 && fup<0) hj=GetBandRejectKernel(fabs(flow),fabs(fup),n,0,0,0,adaptn);
5375
5376 if (flow<0 && fup>0) hj=GetLowPassKernel(fup,n,0,0,0,adaptn);
5377
5378 if (flow>0 && fup<0) hj=GetHighPassKernel(flow,n,0,0,0,adaptn);
5379
5380 SetWaveform(&hj);
5381
5382 if (first)
5383 {
5384 h=hj;
5385 first=kFALSE;
5386 }
5387 else
5388 {
5389 Load(&h);
5390 h=Convolve();
5391 }
5392 }
5393
5394 HistogramFilterFFT(&h,hisf,dB,kTRUE,hist);
5395
5396 // Set the appropriate histogram titles
5397 TString title;
5398 if (hisf)
5399 {
5400 title.Form("%-s MultiBand Filter: Frequency domain kernel for %-i bands (%-i-point time domain kernel each)",ClassName(),neff,n);
5401 hisf->SetTitle(title);
5402 }
5403
5404 if (hist)
5405 {
5406 title.Form("%-s MultiBand Filter: Time domain kernel (zero padded) for %-i bands (%-i-point kernel each)",ClassName(),neff,n);
5407 hist->SetTitle(title);
5408 }
5409
5410 // Restore the original input data
5411 Load(&xsave);
5412 SetWaveform(&wfsave);
5413
5414 // Let user invokations of Load() reset the output data again
5415 fKeepOutput=kFALSE;
5416
5417 return h;
5418}
5419
5420void NcDSP::HistogramFilterFFT(TArray* h,TH1* hisf,Bool_t dB,Bool_t kernel,TH1* hist)
5421{
5433
5434 if (hisf) hisf->Reset("M");
5435 if (hist) hist->Reset("M");
5436
5437 if (!h) return;
5438
5439 Int_t nh=h->GetSize();
5440
5441 // Create a temporary array to contain a zero padded copy
5442 // of the input time domain array "h".
5443 // This allows to get a better view in the time domain filter kernel
5444 // and a better resolution in the DFT produced frequency spectrum.
5445 Int_t npad=0; // The total number of padded zeros
5446 Int_t nfront=0; // The number of padded zeros at the front of the array
5447 Int_t narr=0; // The length of the zero padded array
5448 TArrayD arr(narr);
5449
5450 // The time domain kernel histogram
5451 if (hist && kernel)
5452 {
5453 // The temporary array will be made twice the length of "h"
5454 // and symmetrically zero padded to display the kernel in the center of the histogram
5455 narr=2*nh;
5456 nfront=nh/2;
5457 arr.Set(narr);
5458 arr.Reset();
5459 for (Int_t i=0; i<nh; i++)
5460 {
5461 arr[nfront+i]=h->GetAt(i);
5462 }
5463
5464 if (fSample>0)
5465 {
5466 hist->SetTitle("NcDSP HistogramFilterFFT time domain kernel (zero padded);Time in seconds;Value");
5467 hist->SetBins(narr,0,double(narr)/fSample);
5468 }
5469 else
5470 {
5471 hist->SetTitle("NcDSP HistogramFilterFFT time domain kernel (zero padded);Sample number;Value");
5472 hist->SetBins(narr,0,narr);
5473 }
5474 for (Int_t i=1; i<=narr; i++)
5475 {
5476 hist->SetBinContent(i,arr[i-1]);
5477 }
5478 hist->SetLineWidth(2);
5479 hist->SetLineColor(kBlue);
5480 }
5481
5482 if (!hisf) return;
5483
5484 // The frequency domain kernel or filter result histogram.
5485 // Create a temporary zero-padded time domain array with a length of narr=2^k for the FFT,
5486 // such that the frequency spectrum contains (narr/2)+1 samples.
5487 // The minimum array length will be 1024 samples.
5488 Int_t k=log(nh)/log(2);
5489 k++;
5490 if (k<10) k=10; // Minimal 1024 samples
5491 narr=pow(2,k);
5492 npad=narr-nh;
5493 nfront=npad/2;
5494
5495 arr.Set(narr);
5496 arr.Reset();
5497 for (Int_t i=0; i<nh; i++)
5498 {
5499 arr[nfront+i]=h->GetAt(i);
5500 }
5501
5502 // Load the temporary zero-padded time domain (kernel) data for Fourier transformation
5503 Load(&arr);
5504
5505 TString sel="dB";
5506 if (!dB) sel="AMP";
5507 if (fSample>0)
5508 {
5509 sel+=" Hz";
5510 }
5511 else
5512 {
5513 sel+=" f";
5514 }
5515
5516 // Perform the Fourier transform
5517 Fourier("R2C",hisf,sel);
5518
5519 // Perform the Fourier transform with the original unpadded time domain data
5520 // in order to store Fourier coefficients that allow retrieving the original
5521 // unpadded time domain filter result via an inverse Fourier transform from
5522 // the frequency domain filter result that was produced here.
5523
5524 // Load the original time domain input data
5525 Load(h);
5526
5527 // Perform the Fourier transform
5528 Fourier("R2C");
5529
5530 // Prevent following internal Load() invokations to reset the output
5531 fKeepOutput=kTRUE;
5532
5533 if (!kernel) return;
5534
5535 // Normalize the maximum amplitude of "hisf" to 1 (or 0 dB)
5536 Double_t max=hisf->GetMaximum();
5537 if (!dB)
5538 {
5539 if (max) hisf->Scale(1./fabs(max));
5540 }
5541 else
5542 {
5543 for (Int_t i=1; i<=hisf->GetNbinsX(); i++)
5544 {
5545 hisf->AddBinContent(i,-max);
5546 }
5547 }
5548 hisf->SetLineWidth(2);
5549 hisf->SetLineColor(kBlue);
5550}
5551
5552TGraph NcDSP::Periodogram(TString tu,Double_t Tmin,Double_t Tmax,Int_t n,TArray& t,TArray& y,TArray* dy,TF1* Z,NcDevice* results) const
5553{
5614
5615 if (results) results->Reset();
5616
5617 TGraph gr;
5618
5619 if (tu!="ps" && tu!="ns" && tu!="sec" && tu!="hour" && tu!="day")
5620 {
5621 printf("*%-s::Periodogram* Unsupported time unit : %-s \n",ClassName(),tu.Data());
5622 return gr;
5623 }
5624
5625 if (Tmin<=0 || (Tmax>Tmin && Tmax<=0) || n<1)
5626 {
5627 printf("*%-s::Periodogram* Inconsistent input : Tmin=%-g Tmax=%-g n=%-i \n",ClassName(),Tmin,Tmax,n);
5628 return gr;
5629 }
5630
5631 // Check the compatibility of the input array sizes
5632 Int_t nt=t.GetSize();
5633 Int_t ny=y.GetSize();
5634 Int_t ndy=ny;
5635 if (dy) ndy=dy->GetSize();
5636
5637 if ((nt+ny+ndy)!=3*nt)
5638 {
5639 if (dy)
5640 {
5641 printf("*%-s::Periodogram* Incompatible input array sizes : nt=%-i ny=%-i ndy=%-i \n",ClassName(),nt,ny,ndy);
5642 }
5643 else
5644 {
5645 printf("*%-s::Periodogram* Incompatible input array sizes : nt=%-i ny=%-i \n",ClassName(),nt,ny);
5646 }
5647 return gr;
5648 }
5649
5650 // Determine the frequency bounds and step size
5651 Float_t fmax=1./Tmin;
5652 Float_t fmin=0;
5653 if (Tmax>Tmin) fmin=1./Tmax;
5654 Float_t fstep=(fmax-fmin)/float(n);
5655
5656 // Create compact internal arrays for efficient processing
5657 Int_t na=0;
5658 Double_t ti,yi,dyi2,wi,zi;
5659 TArrayD tarr(nt);
5660 TArrayD yarr(nt);
5661 TArrayD warr(nt);
5662 TArrayD zarr(nt);
5663 Double_t Y=0;
5664 Double_t Y2=0;
5665 for (Int_t i=0; i<nt; i++)
5666 {
5667 ti=t.GetAt(i);
5668 yi=y.GetAt(i);
5669 wi=1;
5670 zi=1;
5671 if (dy)
5672 {
5673 dyi2=pow(dy->GetAt(i),2);
5674 if (!dyi2) continue;
5675 wi=1./dyi2;
5676 }
5677 if (Z) zi=Z->Eval(ti);
5678 tarr[na]=ti;
5679 yarr[na]=yi;
5680 warr[na]=wi;
5681 zarr[na]=zi;
5682 Y+=wi*yi;
5683 Y2+=wi*pow(yi,2);
5684 na++;
5685 }
5686
5687 tarr.Set(na);
5688 yarr.Set(na);
5689 warr.Set(na);
5690 Double_t W=warr.GetSum();
5691
5692 if (!na || W<=0)
5693 {
5694 printf("*%-s::Periodogram* No valid data available. \n",ClassName());
5695 return gr;
5696 }
5697
5698 Y=Y/W;
5699 Y2=Y2/W;
5700
5701 // Loop over the frequencies
5702 Double_t twopi=2.*acos(-1.);
5703 Double_t omega=0;
5704 Double_t zcosi=0;
5705 Double_t zsini=0;
5706 Double_t C=0;
5707 Double_t S=0;
5708 Double_t CS=0;
5709 Double_t C2=0;
5710 Double_t S2=0;
5711 Double_t YC=0;
5712 Double_t YS=0;
5713 Double_t D=0;
5714 Double_t P=0;
5715 Double_t a=0;
5716 Double_t b=0;
5717 Double_t c=0;
5718 Int_t ip=0;
5719 NcSignal sx;
5720 sx.AddNamedSlot("f");
5721 sx.AddNamedSlot("a");
5722 sx.AddNamedSlot("b");
5723 sx.AddNamedSlot("c");
5724 sx.AddNamedSlot("P");
5725 Float_t f=fmin;
5726 fmax+=0.1*fstep; // To prevent accuracy issues
5727 while (f<=fmax)
5728 {
5729 omega=twopi*f;
5730 C=0;
5731 S=0;
5732 CS=0;
5733 C2=0;
5734 S2=0;
5735 YC=0;
5736 YS=0;
5737 // Loop over the data points
5738 for (Int_t i=0; i<na; i++)
5739 {
5740 ti=tarr[i];
5741 yi=yarr[i];
5742 wi=warr[i]/W;
5743 zi=zarr[i];
5744 zcosi=zi*cos(omega*ti);
5745 zsini=zi*sin(omega*ti);
5746 C+=wi*zcosi;
5747 S+=wi*zsini;
5748 CS+=wi*zcosi*zsini;
5749 C2+=wi*pow(zcosi,2);
5750 S2+=wi*pow(zsini,2);
5751 YC+=wi*yi*zcosi;
5752 YS+=wi*yi*zsini;
5753 }
5754
5755 CS-=C*S;
5756 Y2-=pow(Y,2);
5757 C2-=pow(C,2);
5758 S2-=pow(S,2);
5759 YC-=Y*C;
5760 YS-=Y*S;
5761
5762 D=C2*S2-pow(CS,2);
5763
5764 P=0;
5765 if (Y2*D) P=(S2*pow(YC,2)+C2*pow(YS,2)-2.*CS*YC*YS)/(Y2*D);
5766
5767 a=0;
5768 b=0;
5769 if (D)
5770 {
5771 a=(YC*S2-YS*CS)/D;
5772 b=(YS*C2-YC*CS)/D;
5773 }
5774 c=Y-a*C-b*S;
5775
5776 // Record this (f,a,b,c,P) dataset as a hit in the (optional) NcDevice "results"
5777 if (results)
5778 {
5779 sx.SetSignal(f,"f");
5780 sx.SetSignal(a,"a");
5781 sx.SetSignal(b,"b");
5782 sx.SetSignal(c,"c");
5783 sx.SetSignal(P,"P");
5784 results->AddHit(sx);
5785 }
5786
5787 // Record this entry in the periodogram graph
5788 gr.SetPoint(ip,f,P);
5789
5790 f+=fstep;
5791 ip++;
5792 }
5793
5794 TString unit="Hz";
5795 if (tu=="ps") unit="THz";
5796 if (tu=="ns") unit="GHz";
5797 if (tu=="hour") unit="1/hour";
5798 if (tu=="day") unit="1/day";
5799 TString title;
5800 title.Form("%-s Periodogram;Frequency in %-s;Normalized Power",ClassName(),unit.Data());
5801 gr.SetNameTitle("Periodogram",title);
5802 gr.SetMarkerStyle(8);
5803 gr.SetMarkerSize(0.5);
5804 gr.SetMarkerColor(kBlue);
5805 gr.SetLineWidth(2);
5806
5807 return gr;
5808}
5809
5810TGraph NcDSP::Periodogram(TString tu,Double_t Tmin,Double_t Tmax,Int_t n,NcSample s,Int_t it,Int_t iy,Int_t idy,TF1* Z,NcDevice* results) const
5811{
5872
5873 TGraph gr;
5874
5875 if (!s.GetStoreMode())
5876 {
5877 printf("*%-s::Periodogram* Error: NcSample storage mode is not activated. \n",ClassName());
5878 return gr;
5879 }
5880
5881 Int_t ndim=s.GetDimension();
5882 Int_t ns=s.GetN();
5883
5884 if (ns<1 || it<1 || it>ndim || iy<1 || iy>ndim || idy<0 || idy>ndim)
5885 {
5886 printf("*%-s::Periodogram* Inconsistent NcSample input: it=%-i iy=%-i idy=%-i #entries=%-i \n",ClassName(),it,iy,idy,ns);
5887 return gr;
5888 }
5889
5890 TArrayD t(ns);
5891 TArrayD y(ns);
5892 TArrayD dy(ns);
5893
5894 for (Int_t i=1; i<=ns; i++)
5895 {
5896 t[i-1]=s.GetEntry(i,it);
5897 y[i-1]=s.GetEntry(i,iy);
5898 if (idy) dy[i-1]=s.GetEntry(i,idy);
5899 }
5900
5901 if (idy) // Uncertainties will be used as weights
5902 {
5903 gr=Periodogram(tu,Tmin,Tmax,n,t,y,&dy,Z,results);
5904 }
5905 else // No weights will be used
5906 {
5907 gr=Periodogram(tu,Tmin,Tmax,n,t,y,0,Z,results);
5908 }
5909
5910 return gr;
5911}
5912
5913TGraph NcDSP::Periodogram(TString tu,Double_t Tmin,Double_t Tmax,Int_t n,NcSample s,TString namet,TString namey,TString namedy,TF1* Z,NcDevice* results) const
5914{
5975
5976 TGraph gr;
5977
5978 // Get the indices corresponding to the specified variable names
5979 Int_t it=s.GetIndex(namet);
5980 Int_t iy=s.GetIndex(namey);
5981 Int_t idy=s.GetIndex(namedy);
5982
5983 // Check for unsupported namedy
5984 if (!idy && namedy!="-") idy=-1;
5985
5986 Int_t ns=s.GetN();
5987
5988 if (ns<1 || it<1 || iy<1 || idy<0)
5989 {
5990 printf("*%-s::Periodogram* Inconsistent NcSample input: namet=%-s namey=%-s namedy=%-s #entries=%-i \n",ClassName(),namet.Data(),namey.Data(),namedy.Data(),ns);
5991 return gr;
5992 }
5993
5994 gr=Periodogram(tu,Tmin,Tmax,n,s,it,iy,idy,Z,results);
5995
5996 return gr;
5997}
5998
5999TGraph NcDSP::Periodogram(TString tu,Double_t Tmin,Double_t Tmax,Int_t n,TH1& h,Bool_t err,TF1* Z,NcDevice* results) const
6000{
6057
6058 TGraph gr;
6059
6060 Int_t nbins=h.GetNbinsX();
6061 Int_t nen=h.GetEntries();
6062
6063 if (nbins<1 || nen<1)
6064 {
6065 printf("*%-s::Periodogram* Inconsistent histogram input: nbins=%-i #entries=%-i \n",ClassName(),nbins,nen);
6066 return gr;
6067 }
6068
6069 TArrayD t(nbins);
6070 TArrayD y(nbins);
6071 TArrayD dy(nbins);
6072
6073 for (Int_t i=1; i<=nbins; i++)
6074 {
6075 t[i-1]=h.GetBinCenter(i);
6076 y[i-1]=h.GetBinContent(i);
6077 if (err) dy[i-1]=h.GetBinError(i);
6078 }
6079
6080 if (err) // Uncertainties will be used as weights
6081 {
6082 gr=Periodogram(tu,Tmin,Tmax,n,t,y,&dy,Z,results);
6083 }
6084 else // No weights will be used
6085 {
6086 gr=Periodogram(tu,Tmin,Tmax,n,t,y,0,Z,results);
6087 }
6088
6089 return gr;
6090}
6091
6092TGraph NcDSP::Periodogram(TString tu,Double_t Tmin,Double_t Tmax,Int_t n,TGraph& g,Bool_t err,TF1* Z,NcDevice* results) const
6093{
6151
6152 TGraph gr;
6153
6154 if (err && !(g.InheritsFrom("TGraphErrors")))
6155 {
6156 printf("*%-s::Periodogram* Error: For weighted fitting the input graph has to be a TGraphErrors object. \n",ClassName());
6157 return gr;
6158 }
6159
6160 Int_t np=g.GetN();
6161
6162 if (np<1)
6163 {
6164 printf("*%-s::Periodogram* Error: Input graph is empty. \n",ClassName());
6165 return gr;
6166 }
6167
6168 TArrayD t(np);
6169 TArrayD y(np);
6170 TArrayD dy(np);
6171
6172 Double_t gx=0;
6173 Double_t gy=0;
6174 for (Int_t i=0; i<np; i++)
6175 {
6176 g.GetPoint(i,gx,gy);
6177 t[i]=gx;
6178 y[i]=gy;
6179 if (err) dy[i]=g.GetErrorY(i);
6180 }
6181
6182 if (err) // Uncertainties will be used as weights
6183 {
6184 gr=Periodogram(tu,Tmin,Tmax,n,t,y,&dy,Z,results);
6185 }
6186 else // No weights will be used
6187 {
6188 gr=Periodogram(tu,Tmin,Tmax,n,t,y,0,Z,results);
6189 }
6190
6191 return gr;
6192}
6193
6194TObject* NcDSP::Clone(const char* name) const
6195{
6205
6206 NcDSP* q=new NcDSP(*this);
6207 if (name)
6208 {
6209 if (strlen(name)) q->SetName(name);
6210 }
6211 return q;
6212}
6213
ClassImp(NcDSP)
void AddNamedSlot(TString s)
Various Digital Signal Processing (DSP) operations for (sequential) data samples.
Definition NcDSP.h:21
void LoadResult()
Definition NcDSP.cxx:691
Int_t GetN(Int_t mode=0) const
Definition NcDSP.cxx:1008
TArrayD FilterMultiBand(TArray &freqs, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4533
void SetSamplingFrequency(Float_t f)
Definition NcDSP.cxx:370
TArrayD FilterLowPass(Double_t fcut, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:3946
TArrayD fImIn
Definition NcDSP.h:84
TArrayD Convolve(TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Int_t shift=0)
Definition NcDSP.cxx:2126
TGraph Periodogram(TString tu, Double_t Tmin, Double_t Tmax, Int_t n, TArray &t, TArray &y, TArray *dy=0, TF1 *Z=0, NcDevice *results=0) const
Definition NcDSP.cxx:5552
TArrayD GetMultiBandKernel(TArray &freqs, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:5278
void HistogramTrafoResult(TString name, Int_t mode, TH1 *hist, TString sel)
Definition NcDSP.cxx:1768
TArrayD fWaveform
Definition NcDSP.h:88
void Hilbert(Int_t mode, TH1 *hist=0, TString sel="none")
Definition NcDSP.cxx:1568
Float_t fSample
Definition NcDSP.h:90
void Fourier(TString mode, TH1 *hist=0, TString sel="none")
Definition NcDSP.cxx:1092
void SetWaveform(Int_t n, Double_t *h, Float_t f=-1)
Definition NcDSP.cxx:716
TArrayD FilterHighPass(Double_t fcut, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4091
TArrayD GetBandRejectKernel(Double_t f1, Double_t f2, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:5153
TArrayD fHisto
Definition NcDSP.h:87
TArrayD fImOut
Definition NcDSP.h:86
Int_t fN
Definition NcDSP.h:81
NcDSP(const char *name="", const char *title="")
Definition NcDSP.cxx:293
void Cosine(Int_t type, TH1 *hist=0, TString sel="none")
Definition NcDSP.cxx:1334
TArrayL64 ADC(Int_t nbits, Double_t range, Double_t Vbias=0, TArray *Vsig=0, TH1 *hist=0, Int_t B=0, Int_t C=3) const
Definition NcDSP.cxx:2798
TString fNorm
Definition NcDSP.h:89
TArrayD GetHighPassKernel(Double_t fcut, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4911
TArrayD FilterMovingAverage(Int_t n, TString mode, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, TH1 *hisf=0, Bool_t dB=kTRUE)
Definition NcDSP.cxx:3698
void Hartley(Int_t mode, TH1 *hist=0, TString sel="none")
Definition NcDSP.cxx:1240
TArrayD GetData(TString mode) const
Definition NcDSP.cxx:1028
TArrayD Digitize(Int_t nbits, Double_t vcal, Int_t mode, TH1 *hist=0, Double_t *stp=0, Double_t *scale=0) const
Definition NcDSP.cxx:2577
TArrayD fReOut
Definition NcDSP.h:85
TArrayD FilterBandReject(Double_t f1, Double_t f2, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4385
void HistogramFilterFFT(TArray *h, TH1 *hisf, Bool_t dB, Bool_t kernel, TH1 *hist=0)
Definition NcDSP.cxx:5420
TArrayD DAC(Int_t nbits, Double_t range, Double_t Vbias=0, TArray *adcs=0, TArray *peds=0, TH1 *hist=0, Int_t B=0, Int_t C=3) const
Definition NcDSP.cxx:3025
virtual ~NcDSP()
Definition NcDSP.cxx:307
TArrayD GetLowPassKernel(Double_t fcut, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4776
TVirtualFFT * fProc
Definition NcDSP.h:80
TArrayD GetMovingAverageKernel(Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0)
Definition NcDSP.cxx:4688
TArrayD SampleAndHold(TF1 f, Double_t step, Double_t vmin, Double_t vmax, TH1 *hist=0, Int_t loc=-1) const
Definition NcDSP.cxx:3357
virtual TObject * Clone(const char *name="") const
Definition NcDSP.cxx:6194
Float_t GetSamplingFrequency() const
Definition NcDSP.cxx:384
Int_t fNwf
Definition NcDSP.h:82
TArrayD fReIn
Definition NcDSP.h:83
TArrayD Correlate(TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Double_t *peak=0, TString norm="NONE")
Definition NcDSP.cxx:2402
TArrayD SampleAndSum(TF1 f, Double_t step, Double_t vmin, Double_t vmax, TH1 *hist=0) const
Definition NcDSP.cxx:3534
void Sine(Int_t type, TH1 *hist=0, TString sel="none")
Definition NcDSP.cxx:1452
Bool_t fKeepOutput
Definition NcDSP.h:91
void Load(Int_t n, Double_t *re, Double_t *im=0, Float_t f=-1)
Definition NcDSP.cxx:395
TArrayD FilterBandPass(Double_t f1, Double_t f2, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Int_t *i1=0, Int_t *i2=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:4236
TArrayD GetBandPassKernel(Double_t f1, Double_t f2, Int_t n, TH1 *hisf=0, Bool_t dB=kTRUE, TH1 *hist=0, Bool_t adaptn=kTRUE)
Definition NcDSP.cxx:5030
void Reset()
Definition NcDSP.cxx:344
TArrayD Transmit(Int_t nbits, Double_t range, Double_t Vbias=0, TArray *Vsig=0, TArray *peds=0, TH1 *hist=0, Int_t B=0, Int_t C=3) const
Definition NcDSP.cxx:3265
Signal (Hit) handling of a generic device.
Definition NcDevice.h:14
void AddHit(NcSignal &s)
Definition NcDevice.cxx:336
virtual void Reset(Int_t mode=0)
Definition NcDevice.cxx:222
Various mathematical tools for scientific analysis.
Definition NcMath.h:26
Double_t Log(Double_t B, Double_t x) const
Definition NcMath.cxx:2613
Sampling and statistics tools for various multi-dimensional data samples.
Definition NcSample.h:28
Int_t GetStoreMode() const
Int_t GetN() const
Int_t GetIndex(TString name) const
Int_t GetDimension() const
Double_t GetEntry(Int_t i, Int_t j, Int_t mode=0, Int_t k=0)
Generic handling of (extrapolated) detector signals.
Definition NcSignal.h:23
virtual void SetSignal(Double_t sig, Int_t j=1)
Definition NcSignal.cxx:516