9 #include "TDirectory.h"
14 #include "TObjString.h"
35 return TString::Format(
"cafanauniq%d", N++).Data();
41 fBackup = TH1::AddDirectoryStatus();
42 TH1::AddDirectory(
false);
54 const char*
s = getenv(
"IFDH_SILENT");
55 fSet = (s && s == std::string(
"0"));
56 if(!
fSet) setenv(
"IFDH_SILENT",
"1", 1);
57 if(s)
std::cout <<
"IFDH_SILENT=" << s << std::endl;
63 if(!
fSet) unsetenv(
"IFDH_SILENT");
71 feclearexcept(FE_INVALID);
73 fegetexceptflag(&
fBackup, FE_INVALID);
77 feenableexcept(FE_INVALID);
79 fedisableexcept(FE_INVALID);
81 std::cerr <<
"WARNING: CAFAna/Core/Utilities.cxx built on OS X, no feenableexcept available" << std::endl;
88 fesetexceptflag(&
fBackup, FE_INVALID);
94 const char* ret = getenv(
"EXPERIMENT");
97 std::cout <<
"\nERROR: Environment variable $EXPERIMENT not set." << std::endl;
107 const char* ret = getenv(
"SAM_EXPERIMENT");
110 std::cout <<
"\nERROR: Environment variable $SAM_EXPERIMENT not set.\nThis is required for various ifdh/sam functionality.\nYou likely want it to be set to 'sbn', though it should have been set automatically by setup scripts." << std::endl;
118 std::unique_ptr<TMatrixD>
CalcCovMx(
const std::vector<TArrayD*> & binSets,
int firstBin,
int lastBin)
120 if (binSets.size() < 2)
121 return std::unique_ptr<TMatrixD>(
nullptr);
124 lastBin = binSets[0]->GetSize() - 1;
126 int nBins = lastBin - firstBin + 1;
128 std::vector<double> binMeans(nBins);
129 for(
const auto & binSet : binSets )
131 for ( decltype(lastBin) binIdx = firstBin; binIdx <= lastBin; binIdx++ )
132 binMeans[binIdx] += (*binSet)[binIdx];
134 for (decltype(lastBin) binIdx = firstBin; binIdx <= lastBin; binIdx++)
135 binMeans[binIdx] /= binSets.size();
138 auto covmx = std::make_unique<TMatrixD>(nBins, nBins);
140 for(
unsigned int hist_idx = 0; hist_idx < binSets.size(); ++hist_idx )
143 for( decltype(nBins) i = 0; i < nBins; i++ )
145 double xi = (*(binSets[hist_idx]))[i];
146 for( decltype(nBins)
k = i;
k < nBins;
k++ )
148 double xk = (*(binSets[hist_idx]))[
k];
149 (*covmx)[i][
k] += (xi - binMeans[i]) * (xk - binMeans[
k]);
151 (*covmx)[
k][i] = (*covmx)[i][
k];
157 (*covmx) *= 1./(binSets.size()-1);
170 const double s = .25*(sqrt(8*o*S2+
util::sqr(e*S2-2))-e*S2-2);
176 const double minexp = 1e-40;
186 return 2*o*((e-o)/o + log1p((o-e)/
e));
193 return 2*(e-o + o*log(o/e));
204 assert(eh->GetNbinsX() == oh->GetNbinsX());
208 int bufferBins = useOverflow? 2 : 1;
210 for(
int i = 0; i < eh->GetNbinsX()+bufferBins; ++i){
211 const double e = eh->GetBinContent(i);
212 const double o = oh->GetBinContent(i);
221 double Chi2CovMx(
const TVectorD*
e,
const TVectorD* o,
const TMatrixD* covmxinv)
223 assert (e->GetNrows() == o->GetNrows());
225 TVectorD diff = *o - *
e;
226 return diff * ((*covmxinv) * diff);
230 double Chi2CovMx(
const TH1*
e,
const TH1* o,
const TMatrixD* covmxinv)
232 TVectorD eVec(e->GetNbinsX());
233 TVectorD oVec(o->GetNbinsX());
234 for (
int bin = 1;
bin <= e->GetNbinsX();
bin++)
235 eVec[
bin-1] = e->GetBinContent(
bin);
236 for (
int bin = 1;
bin <= o->GetNbinsX();
bin++)
237 oVec[
bin-1] = o->GetBinContent(
bin);
239 return Chi2CovMx(&eVec, &oVec, covmxinv);
244 int nbinsx,
double xmin,
double xmax,
bool xlog,
245 int nbinsy,
double ymin,
double ymax,
bool ylog)
249 if(xlog){xmin = log(xmin); xmax = log(xmax);}
250 if(ylog){ymin = log(ymin); ymax = log(ymax);}
253 const double xwidth = (xmax-
xmin)/(nbinsx-1);
254 const double ywidth = (ymax-ymin)/(nbinsy-1);
257 xmin -= xwidth/2; ymin -= ywidth/2;
258 xmax += xwidth/2; ymax += ywidth/2;
260 std::vector<double> xedges(nbinsx+1);
261 std::vector<double> yedges(nbinsy+1);
263 for(
int i = 0; i <= nbinsx; ++i){
264 xedges[i] = xmin + (xmax-
xmin)*i/
double(nbinsx);
265 if(xlog) xedges[i] =
exp(xedges[i]);
267 for(
int i = 0; i <= nbinsy; ++i){
268 yedges[i] = ymin + (ymax-ymin)*i/
double(nbinsy);
269 if(ylog) yedges[i] =
exp(yedges[i]);
272 return new TH2F(
UniqueName().c_str(), title.c_str(),
273 nbinsx, &xedges.front(),
274 nbinsy, &yedges.front());
285 std::set<int> nullRows;
286 for (
auto row = mx.GetRowLwb();
row <= mx.GetRowUpb();
row++)
288 bool rowIsNull =
true;
289 for (
auto col = mx.GetColLwb(); col <= mx.GetColUpb(); col++)
291 if (mx[
row][col] != 0.)
299 nullRows.insert(
row);
302 std::cerr <<
" Notice: covariance matrix '" << mx.GetName() <<
"' has " << nullRows.size() <<
" null rows.\n"
303 <<
"They will be removed before inverting and added back afterwards." << std::endl;
306 auto invMx = std::make_unique<TMatrixD>(mx.GetRowLwb(), mx.GetRowUpb() - nullRows.size(),
307 mx.GetColLwb(), mx.GetColUpb() - nullRows.size());
308 unsigned int skippedRows = 0;
309 for (
auto row = mx.GetRowLwb();
row <= mx.GetRowUpb();
row++)
311 if (nullRows.find(
row) != nullRows.end())
316 unsigned int skippedCols = 0;
317 for (
auto col = mx.GetColLwb(); col <= mx.GetColUpb(); col++)
321 if (nullRows.find(col) != nullRows.end())
327 (*invMx)[col-skippedCols][
row-skippedRows] = (*invMx)[
row-skippedRows][col-skippedCols] = mx[
row][col];
337 auto retMx = std::make_unique<TMatrixD>(mx.GetRowLwb(), mx.GetRowUpb(),
338 mx.GetColLwb(), mx.GetColUpb());
339 for (
auto row = mx.GetRowLwb();
row <= mx.GetRowUpb();
row++)
341 if (nullRows.find(
row) != nullRows.end())
347 unsigned int skippedCols = skippedRows;
348 for (
auto col =
row; col <= mx.GetColUpb(); col++)
350 if (nullRows.find(col) != nullRows.end())
356 (*retMx)[col][
row] = (*retMx)[
row][col] = (*invMx)[
row-skippedRows][col-skippedCols];
370 template<
class T,
class...
A> T* MakeHist(
A...
a)
372 DontAddDirectory guard;
378 template<
class T,
class...
A> T* MakeHist(
const Binning& firstBin,
381 if(firstBin.IsSimple())
382 return MakeHist<T>(
args...,
383 firstBin.NBins(), firstBin.Min(), firstBin.Max());
385 return MakeHist<T>(
args...,
386 firstBin.NBins(), &firstBin.Edges().front());
395 return MakeHist<TH1D>(bins,
name, title);
403 return MakeHist<TH2D>(binsx, binsy,
name, title);
412 std::unique_ptr<TH1> h1(s.
ToTH1(exposure, expotype));
413 return ToTH2Helper(std::move(h1), binsx, binsy, bintype);
422 std::unique_ptr<TH1> h1(r.
ToTH1());
432 assert(h1->GetNbinsX() == binsx.
NBins()*binsy.
NBins());
436 for(
int i = 0; i < h1->GetNbinsX(); ++i){
437 const double val = h1->GetBinContent(i+1);
438 const double err = h1->GetBinError(i+1);
440 const int ix = i / binsy.
NBins();
441 const int iy = i % binsy.
NBins();
443 ret->SetBinContent(ix+1, iy+1, val);
444 ret->SetBinError (ix+1, iy+1, err);
460 std::unique_ptr<TH1> h1(s.
ToTH1(exposure, expotype));
462 return ToTH3Helper(std::move(h1), binsx, binsy, binsz, bintype);
472 std::unique_ptr<TH1> h1(r.
ToTH1());
474 return ToTH3Helper(std::move(h1), binsx, binsy, binsz);
485 const int nx = binsx.
NBins();
486 const int ny = binsy.
NBins();
487 const int nz = binsz.
NBins();
490 assert(h1->GetNbinsX() == nx*ny*nz);
497 nx, binsx.
Min(), binsx.
Max(),
498 ny, binsy.
Min(), binsy.
Max(),
499 nz, binsz.
Min(), binsz.
Max());
503 std::cerr <<
"ToTH3: one or more axes is custom, but not all three. Applying Simple binning to all three axes" << std::endl;
508 nx, &binsx.
Edges().front(),
509 ny, &binsy.
Edges().front(),
510 nz, &binsz.
Edges().front());
513 for(
int i = 0; i < h1->GetNbinsX(); ++i){
514 const double val = h1->GetBinContent(i+1);
515 const double err = h1->GetBinError(i+1);
517 const int nynz = ny*nz;
518 const int nmodnynz = i%nynz;
519 const int ix = i/nynz;
520 const int iy = nmodnynz/nz;
523 ret->SetBinContent(ix+1, iy+1, iz+1, val);
524 ret->SetBinError (ix+1, iy+1, iz+1, err);
534 std::vector<std::string>
Wildcard(
const std::string& wildcardString)
538 const int status = wordexp(wildcardString.c_str(), &
p, WRDE_SHOWERR);
541 std::cerr <<
"Wildcard string '" << wildcardString
542 <<
"' returned error " << status <<
" from wordexp()."
547 std::vector<std::string> fileList;
549 for(
unsigned int i = 0; i < p.we_wordc; ++i){
552 if(
stat(p.we_wordv[i], &sb) == 0)
553 fileList.push_back(p.we_wordv[i]);
564 return std::string(getenv(
"MRB_SOURCE"))+
"/sbnana/sbnana/CAFAna";
570 std::vector<std::string> ret;
572 std::ifstream is(listfile);
574 std::cerr <<
"Can't open file list '" << listfile <<
"'. Aborting." << std::endl;
581 if(!fname.empty()) ret.push_back(fname);
589 std::map<std::string, std::string> ret;
591 TTree* tr = (TTree*)dir->Get(
"metatree");
593 std::cout <<
"Failed to find metadata tree in input CAF. Metadata will be blank." << std::endl;
597 std::string key,
value;
598 std::string* pkey = &key;
599 std::string* pvalue = &
value;
600 tr->SetBranchAddress(
"key", &pkey);
601 tr->SetBranchAddress(
"value", &pvalue);
603 for(
int i = 0; i < tr->GetEntries(); ++i){
613 const std::map<std::string, std::string>& add,
614 std::set<std::string>&
mask)
617 const std::string& key = it.first;
620 if(key ==
"parents")
continue;
624 const std::string& r1 = base[key];
625 const std::string& r2 = it.second;
630 const std::string& r2tmp = r2.substr(1, r2.length()-2);
633 if (r1.find(r2tmp) != std::string::npos){
634 std::cout <<
"Found files with duplicate run/subrun metadata: " << r2tmp << std::endl;
645 std::string sum = r1+&r2[1];
646 sum[r1.size()-1] =
',';
651 if(base.find(key) == base.end()){
653 base[key] = it.second;
656 if(key ==
"simulated.number_of_spills" ||
657 key ==
"event_count" ||
658 key ==
"online.totalevents"){
660 base[key] = TString::Format(
"%d",
661 atoi(base[key].c_str()) +
662 atoi(it.second.c_str())).Data();
666 if(base[key] != it.second) mask.insert(key);
675 const std::map<std::string, std::string>& meta)
677 TDirectory* tmp = gDirectory;
680 TTree* trmeta =
new TTree(
"metatree",
"metatree");
681 std::string key,
value;
682 trmeta->Branch(
"key", &key);
683 trmeta->Branch(
"value", &value);
684 for(
const auto& keyval: meta){
686 value = keyval.second;
700 static bool cache_set =
false;
702 cache = (getenv(
"_CONDOR_SCRATCH_DIR") != 0);
712 static int cache = -1;
715 char* env = getenv(
"CAFANA_STRIDE");
717 cache = std::atoi(env);
724 std::cout <<
"Stride() called, but CAFANA_STRIDE is not set (--stride not passed?)" << std::endl;
736 static int cache = -1;
739 char* env = getenv(
"CAFANA_OFFSET");
741 cache = std::atoi(env);
748 std::cout <<
"Offset() called, but CAFANA_OFFSET is not set (--offset not passed?)" << std::endl;
760 static int cache = 0;
763 char* env = getenv(
"CAFANA_LIMIT");
765 cache = std::atoi(env);
779 std::cout <<
"JobNumber() called, but we are not running on the grid" << std::endl;
790 std::cout <<
"NumJobs() called, but we are not running on the grid" << std::endl;
801 if(a == 0 && b == 0)
return true;
803 return fabs(a-b)/std::max(a, b) < .0001;
810 static bool first =
true;
811 static bool onsite =
false;
813 if (first && unauth) {
816 gethostname(chostname, 255);
817 std::string hostname = chostname;
819 if ( hostname.find(
"fnal.gov") != std::string::npos ){
821 std::cout <<
"Using unauthenticated xrootd access (port 1095) while on-site, hostname: " << hostname << std::endl;
825 std::cout <<
"Using authenticated xrootd access (port 1094) access while off-site, hostname: " << hostname << std::endl;
829 if(loc.rfind(
"/pnfs/", 0) == 0){
830 if ( onsite && unauth )
831 loc = std::string(
"root://fndcagpvm01.fnal.gov:1095//pnfs/fnal.gov/usr/")+&loc.c_str()[6];
833 loc = std::string(
"root://fndcagpvm01.fnal.gov:1094//pnfs/fnal.gov/usr/")+&loc.c_str()[6];
839 FitToFourier::FitToFourier(TH1*
h,
double xlo,
double xhi,
int NOsc)
840 : fHist(h), fxlo(xlo), fxhi(xhi), fNOsc(NOsc)
845 FitToFourier::~FitToFourier()
850 double FitToFourier::operator()(
double *
x,
double *par)
const
854 for (
int i = 1; i <= fNOsc; i++)
855 val += par[2*i-1]*sin(i*M_PI*x0) + par[2*i]*cos(i*M_PI*x0);
860 TF1* FitToFourier::Fit()
const
865 std::vector<double>
s(fNOsc, 0.0);
866 std::vector<double> c(fNOsc, 0.0);
869 for(
int i = 1; i <= fHist->GetNbinsX(); ++i){
870 const double x = M_PI * fHist->GetXaxis()->GetBinCenter(i);
871 const double y = fHist->GetBinContent(i);
876 for(
int n = 0;
n <= fNOsc; ++
n){
877 s[
n] += y * sin(
n*x);
878 c[
n] += y * cos(
n*x);
882 for(
int n = 0;
n <= fNOsc; ++
n){
887 TF1* f =
new TF1(
UniqueName().c_str(),
this, fxlo, fxhi, 2*fNOsc+1);
889 f->SetParameter(0, c[0]/2);
890 for(
int n = 1;
n <= fNOsc; ++
n){
891 f->SetParameter(
n*2-1,
s[
n]);
892 f->SetParameter(n*2, c[n]);
896 double min = fHist->GetMinimum();
897 double max = fHist->GetMaximum();
898 f->GetYaxis()->SetRangeUser(0.8*min, 1.2*max);
906 assert(mat->GetNbinsX() == mat->GetNbinsY());
907 const int N = mat->GetNbinsX();
909 for(
int i = 0; i <
N; ++i)
910 for(
int j = 0; j <
N; ++j)
911 m(i, j) = mat->GetBinContent(i+1, j+1);
915 TMatrixD evecs = m.EigenVectors(evals);
916 TMatrixD evalmat(N, N);
918 for(
int i = 0; i <
N; ++i) evalmat(i, i) = std::max(1
e-14, evals[i]);
921 const TMatrixD evecs_inv(TMatrixD::kTransposed, evecs);
922 m = evecs*evalmat*evecs_inv;
925 m.EigenVectors(evals);
926 for(
int i = 0; i < N; ++i) assert(evals[i] > 0);
929 for(
int i = 0; i <
N; ++i)
930 for(
int j = 0; j <
N; ++j)
931 mat->SetBinContent(i+1, j+1, m(i, j));
939 std::cout <<
"Error: unable to apply a mask in " << s.
GetBinnings().size() <<
" dimensions" << std::endl;
947 int ybins = fMaskND->GetNbinsY();
949 for(
int i = 0; i < fMask1D->GetNbinsX()+2; ++i){
957 if (fMaskND->GetXaxis()->GetBinLowEdge(ix+1) <
xmin) isMask=
true;
958 if (fMaskND->GetXaxis()->GetBinUpEdge(ix+1) > xmax) isMask=
true;
962 if (fMaskND->GetYaxis()->GetBinLowEdge(iy+1) < ymin) isMask=
true;
963 if (fMaskND->GetYaxis()->GetBinUpEdge(iy+1) > ymax) isMask=
true;
966 if (isMask) fMask1D->SetBinContent(i+1, 0);
967 else fMask1D->SetBinContent(i+1, 1);
982 std::sort(xs.begin(), xs.end());
984 const int N = xs.size();
986 const double h = frac*(N+1);
988 const unsigned int h0 = std::floor(h);
989 const unsigned int h1 = std::ceil(h);
990 if(h0 == 0)
return xs[0];
991 if(h1 > xs.size())
return xs.back();
993 const double x0 = xs[h0-1];
994 const double x1 = xs[h1-1];
996 if(h0 == h1)
return x0;
999 return (h1-h)*x0 + (h-h0)*x1;
TH2D * MakeTH2D(const char *name, const char *title, const Binning &binsx, const Binning &binsy)
see a below echo S(symbol in a section other than those above)
TH1D * ToTH1(double exposure, Color_t col=kBlack, Style_t style=kSolid, EExposureType expotype=kPOT, EBinType bintype=kBinContent) const
Histogram made from this Spectrum, scaled to some exposure.
Represent the binning of a Spectrum's x-axis.
TH1D * ToTH1(Color_t col=kBlack, Style_t style=kSolid) const
process_name opflash particleana ie x
BEGIN_PROLOG could also be cerr
size_t Offset(bool allow_default)
TH3 * ToTH3Helper(std::unique_ptr< TH1 > h1, const Binning &binsx, const Binning &binsy, const Binning &binsz, ana::EBinType bintype)
double LogLikelihood(double e, double o)
The log-likelihood formula for a single bin.
EResult err(const char *call)
TH2 * ToTH2Helper(std::unique_ptr< TH1 > h1, const Binning &binsx, const Binning &binsy, ana::EBinType bintype)
void CombineMetadata(std::map< std::string, std::string > &base, const std::map< std::string, std::string > &add, std::set< std::string > &mask)
Divide bin contents by bin widths.
std::vector< std::string > Wildcard(const std::string &wildcardString)
double FindQuantile(double frac, std::vector< double > &xs)
std::unique_ptr< TMatrixD > SymmMxInverse(const TMatrixD &mx)
process_name opflashCryoW ana
std::string pnfs2xrootd(std::string loc, bool unauth)
void EnsurePositiveDefinite(TH2 *mat)
std::string FindCAFAnaDir()
T sqr(T x)
More efficient square function than pow(x,2)
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
Representation of a spectrum in any variable, with associated POT.
FloatingExceptionOnNaN(bool enable=true)
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
std::map< std::string, std::string > GetCAFMetadata(TDirectory *dir)
TH2F * ExpandedHistogram(const std::string &title, int nbinsx, double xmin, double xmax, bool xlog, int nbinsy, double ymin, double ymax, bool ylog)
process_name opflash particleana ie ie y
constexpr mask_t< EnumType > mask(EnumType bit, OtherBits...otherBits)
Returns a mask with all specified bits set.
std::string Experiment()
$EXPERIMENT or a nice error message and abort
std::unique_ptr< TMatrixD > CalcCovMx(const std::vector< TArrayD * > &binSets, int firstBin, int lastBin)
Compute bin-to-bin covariance matrix from a collection of sets of bin contents.
EExposureType
For use as an argument to Spectrum::ToTH1.
TH1 * ToTHX(double exposure, bool force1D=false, EExposureType expotype=kPOT) const
Function decides what is the appropriate projection based on fBins, and does that.
void WriteCAFMetadata(TDirectory *dir, const std::map< std::string, std::string > &meta)
bool AlmostEqual(double a, double b)
TH2 * ToTH2(const Spectrum &s, double exposure, ana::EExposureType expotype, const Binning &binsx, const Binning &binsy, ana::EBinType bintype)
Represent the ratio between two spectra.
const std::vector< double > & Edges() const
TH1D * MakeTH1D(const char *name, const char *title, const Binning &bins)
size_t Stride(bool allow_default)
then echo File list $list not found else cat $list while read file do echo $file sed s
std::string SAMExperiment()
$SAM_EXPERIMENT or a nice error message and abort
process_name largeant stream1 can override from command line with o or output physics producers generator N
~FloatingExceptionOnNaN()
std::vector< std::string > LoadFileList(const std::string &listfile)
Prevent histograms being added to the current directory.
TH3 * ToTH3(const Spectrum &s, double exposure, ana::EExposureType expotype, const Binning &binsx, const Binning &binsy, const Binning &binsz, ana::EBinType bintype)
TH1 * GetMaskHist(const Spectrum &s, double xmin, double xmax, double ymin, double ymax)
std::string UniqueName()
Return a different string each time, for creating histograms.
BEGIN_PROLOG could also be cout
double Chi2CovMx(const TVectorD *e, const TVectorD *o, const TMatrixD *covmxinv)
std::vector< Binning > GetBinnings() const