6 #include <TMatrixDSym.h>
23 #include <Math/Integrator.h>
31 double f = 1.27 * dm2;
32 return (energy / (4 * f)) * (TMath::Sin(2 * f * l_min / energy) - TMath::Sin(2 * f * l_max / energy));
39 return 1 - sin * TMath::Power(TMath::Sin(1.27 * dm2 * x), 2);
45 return sin * TMath::Power(TMath::Sin(1.27 * dm2 * x), 2);
48 double NumuOscillate(ROOT::Math::IntegratorOneDim &integrator,
double l_min,
double l_max,
double e_min,
double e_max,
double dm2,
double sinth) {
49 auto integrand = [l_min, l_max, dm2](
double energy) {
return osc_factor_L_integrated(energy, l_min, l_max, dm2); };
50 double integral = integrator.Integral(integrand, e_min, e_max);
51 double factor = (1. / 2. ) + integral / ( (l_max - l_min)*(e_max - e_min));
52 return 1 - sinth * factor;
58 ROOT::Math::IntegratorOneDim integrator;
60 std::vector<double> ret(
fBkgCounts->GetNbinsX(), 0);
62 for (
unsigned Ebin = 0; Ebin <
fSignalCounts->GetNbinsY(); Ebin++) {
64 for (
unsigned Dbin = 0; Dbin <
fSignalCounts->GetNbinsZ(); Dbin++) {
86 std::vector<double> ret(fBkgCounts->GetNbinsX(), 0);
88 for (
unsigned Ebin = 0; Ebin < fSignalCounts->GetNbinsY(); Ebin++) {
89 for (
unsigned Dbin = 0; Dbin < fSignalCounts->GetNbinsZ(); Dbin++) {
90 for (
unsigned bin = 0;
bin < fSignalCounts->GetNbinsX();
bin++) {
91 double counts = fSignalCounts->GetBinContent(
bin+1, Ebin+1, Dbin+1);
102 std::vector<double> ret(fBkgCounts->GetNbinsX(), 0);
103 for (
unsigned bin = 0;
bin < fBkgCounts->GetNbinsX();
bin++) {
104 ret[
bin] = fBkgCounts->GetBinContent(
bin+1);
115 assert(config != NULL);
121 fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>(
"Sensitivity");
122 fOutputFile = pconfig.get<std::string>(
"OutputFile",
"output.root");
125 fEnergyType = pconfig.get<std::string>(
"EnergyType",
"Reco");
132 std::vector<fhicl::ParameterSet> samples = \
133 config->get<std::vector<fhicl::ParameterSet> >(
"EventSamples");
134 for (
const fhicl::ParameterSet& sample: samples) {
139 fNumDm2 = pconfig.get<
int>(
"NumDm2", 50);
140 fLogDm2Lims = pconfig.get<std::vector<double> >(
"LogDm2Lims");
141 fNumSin = pconfig.get<
int>(
"NumSin", 50);
142 fLogSinLims = pconfig.get<std::vector<double> >(
"LogSinLims");
145 fSavePDFs = pconfig.get<
bool>(
"SavePDFs",
true);
146 fSaveSignal = pconfig.get<
bool>(
"SaveSignal",
true);
149 if (pconfig.is_key_to_sequence(
"SaveOscillations")) {
150 std::vector<std::vector<double> > pairs = \
151 pconfig.get<std::vector<std::vector<double> > >(
"SaveOscillations");
152 for (
size_t i=0; i<pairs.size(); i++) {
163 fName = config.get<std::string>(
"name",
"");
164 fScalePOT = config.get<
double>(
"ScalePOT", 0.);
168 std::vector<double> xlim = config.get<std::vector<double> >(
"DetX");
169 std::vector<double> ylim = config.get<std::vector<double> >(
"DetY");
170 std::vector<double> zlim = config.get<std::vector<double> >(
"DetZ");
179 fOscType = config.get<
int>(
"OscType", 0);
184 std::vector<double> bins = config.get<std::vector<double> >(
"binlims");
185 for (
auto const&
bin: bins) {
190 std::vector<double> truee = config.get<std::vector<double> >(
"TrueELims");
191 double minTrueE = truee.at(0);
192 double maxTrueE = truee.at(1);
193 int numTrueEBinLimits = config.get<
int>(
"NumTrueEBins", 1) + 1;
194 double trueE_binwidth = (maxTrueE - minTrueE) / numTrueEBinLimits;
195 for (
int i = 0; i < numTrueEBinLimits; i ++) {
196 fTrueEBins.push_back(minTrueE + i * trueE_binwidth);
202 int numBinsPerMeter = config.get<
int>(
"NumDistanceBinsPerMeter", 1);
203 double numBinsPerCM = numBinsPerMeter * 0.01;
206 fBaseline = config.get<
double>(
"Baseline");
207 fBeamCenterX = config.get<
double>(
"BeamCenterX", 0.);
208 fBeamCenterY = config.get<
double>(
"BeamCenterY", 0.);
209 fBeamFrontZ = config.get<
double>(
"BeamFrontZ", 0.);
212 double detector_distance = sqrt((fZlim[1] - fZlim[0]) * (fZlim[1] - fZlim[0]) \
213 + (fXlim[1] - fXlim[0]) * (fXlim[1] - fXlim[0]) \
214 + (fYlim[1] - fYlim[0]) * (fYlim[1] - fYlim[0]));
217 double beam_width = sqrt( 125. * 125. + 125. * 125. + 5500. * 5500. );
218 unsigned n_bins = (unsigned) ((detector_distance + beam_width) * numBinsPerCM) + 1;
219 unsigned n_limits = n_bins + 1;
220 double dist_binwidth = 1./numBinsPerCM;
226 for (
unsigned i = 0; i < n_limits; i++) {
227 fDistBins.push_back((min_baseline + (i * dist_binwidth)) / 100000. );
231 fEnergyBinScale = config.get<std::vector<double>>(
"energy_bin_scale", {});
232 if (fEnergyBinScale.size() == 0) {
233 fEnergyBinScale = std::vector<double>(
fBins.size() - 1, 1.0);
235 else assert(fEnergyBinScale.size() ==
fBins.size() - 1);
238 fBkgCounts =
new TH1D((fName +
" Background").c_str(), (fName +
" Background").c_str(),
fBins.size() - 1, &
fBins[0]);
239 fSignalCounts =
new TH3D((fName +
" Signal").c_str(), (fName +
" Signal").c_str(),
240 fBins.size() - 1, &
fBins[0], fTrueEBins.size() - 1, &fTrueEBins[0], fDistBins.size() - 1, &fDistBins[0]);
262 for (
int n = 0;
n <
event->reco.size();
n++) {
263 unsigned truth_ind =
event->reco[
n].truth_index;
266 int idx =
event->reco[
n].truth_index;
267 if (idx < 0 || idx > event->
truth.size()) {
270 double true_nuE =
event->truth[idx].neutrino.energy;
273 nuE =
event->truth[truth_ind].neutrino.eccqe;
277 nuE =
event->reco[
n].reco_energy;
282 TVector3 p_decay_vtx =
event->truth[truth_ind].neutrino.parentDecayVtx;
283 TVector3 neutrino_vtx =
event->truth[truth_ind].neutrino.position;
288 double dist = sqrt(dx*dx + dy*dy + dz*dz) / 100000. ;
296 std::cout << std::endl <<
"NUE IN RANGE, TRUE E NOT!!! nuE = " << nuE <<
" and true_nuE = " << true_nuE << std::endl;
301 std::cout << std::endl <<
"NUE IN RANGE, DISTANCE NOT!! nuE = " << nuE <<
" and distance = " << dist << std::endl;
308 int isCC =
event->truth[truth_ind].neutrino.iscc;
316 double wgt =
event->reco[
n].weight;
336 for (
int sample = 0; sample <
fEventSamples.size(); sample++) {
337 for (
int i = 1; i <
fEventSamples[sample].fSignalCounts->GetNbinsX()+1; i++) {
339 for (
int j = 1; j <
fEventSamples[sample].fSignalCounts->GetNbinsY()+1; j++) {
340 for (
int k = 1;
k <
fEventSamples[sample].fSignalCounts->GetNbinsZ()+1;
k++) {
341 double content =
fEventSamples[sample].fSignalCounts->GetBinContent(i, j,
k);
343 fEventSamples[sample].fSignalCounts->SetBinContent(i, j,
k, content * scale);
349 for (
int i = 1; i <
fEventSamples[sample].fBkgCounts->GetNbinsX()+1; i++) {
351 double content =
fEventSamples[sample].fBkgCounts->GetBinContent(i);
352 fEventSamples[sample].fBkgCounts->SetBinContent(i, content * scale);
363 std::cout << std::endl <<
"Inverting full error matrix, E_{ij}..." << std::endl;
370 TMatrixD E_inv = E_mat.Invert();
381 for (
int i = 0; i <
fNumSin; i++) {
384 for (
int j = 0; j <
fNumDm2; j++) {
389 clock_t startchi = clock();
390 std::cout << std::endl <<
"Calculating chi squareds..." << std::endl;
392 double minchisq = 1e99;
393 std::vector <double> chisq_dm2(fNumDm2, 0);
394 std::vector <std::vector <double> > chisq(fNumSin, chisq_dm2);
396 std::vector<double> signal;
400 std::vector<double> this_signal = sample.Signal();
401 signal.insert(signal.end(), this_signal.begin(), this_signal.end());
404 for (
int j = 0; j <
fNumDm2; j++) {
405 std::vector<std::vector<double>> oscillated;
408 for (
auto const &sample: fEventSamples) {
410 oscillated.push_back(sample.Oscillate(1.,
dm2[j]));
414 std::vector<double> sin2_oscillated(signal.size(), 0);
416 for (
int i = 0; i <
fNumSin; i++) {
418 unsigned count_ind = 0;
419 for (
unsigned sample_ind = 0; sample_ind < oscillated.size(); sample_ind++) {
420 for (
unsigned bin_ind = 0; bin_ind < oscillated[sample_ind].size(); bin_ind++) {
422 if (fEventSamples[sample_ind].fOscType == 0) {
423 sin2_oscillated[count_ind] = signal[count_ind];
426 else if (fEventSamples[sample_ind].fOscType == 1) {
427 sin2_oscillated[count_ind] =
sin2theta[i] * oscillated[sample_ind][bin_ind];
430 else if (fEventSamples[sample_ind].fOscType == 2) {
441 sin2_oscillated[count_ind] = signal[count_ind] * (1 -
sin2theta[i]) +
442 sin2theta[i] * oscillated[sample_ind][bin_ind];
450 assert(count_ind == signal.size());
453 for (
int k = 0;
k < signal.size();
k++) {
454 for (
int l = 0; l < signal.size(); l++) {
455 chisq[i][j] += (signal[
k] - sin2_oscillated[
k]) * (signal[l] - sin2_oscillated[l]) * E_inv[
k][l];
460 if (chisq[i][j] < minchisq) {
461 minchisq = chisq[i][j];
467 clock_t endchi = clock();
468 clock_t tickschi = endchi - startchi;
469 double timechi = tickschi / (double) CLOCKS_PER_SEC;
471 std::cout <<
" Done in " << timechi <<
"s. " << std::endl;
476 for (
int i = 0; i <
fNumSin; i++) {
477 for (
int j = 0; j <
fNumDm2; j++) {
484 for (
int i = 0; i <
fNumSin; i++) {
485 for (
int j = 0; j <
fNumDm2; j++) {
503 clock_t startcont = clock();
504 std::cout << std::endl <<
"Getting contours..." << std::endl;
508 std::vector <double> target_dchisq = {1.64, 7.75, 23.40}, corners(4, 0), twozeros(2, 0);
509 std::vector <std::vector <double> > contour, sin_contour(target_dchisq.size()), dm2_contour(target_dchisq.size()), vecof2vecs(
fNumDm2, twozeros);
510 std::vector <std::vector <std::vector <double> > > box_minmax(
fNumSin, vecof2vecs);
511 for (
int k = 0;
k < target_dchisq.size();
k++){
513 target = target_dchisq[
k];
516 for (
int i = 0; i <
fNumSin-1; i++) {
517 for (
int j = 0; j <
fNumDm2-1; j++) {
518 box_minmax[i][j] = {0, 0};
523 for (
int i = 0; i < fNumSin-1; i++) {
524 for (
int j = 0; j <
fNumDm2-1; j++) {
527 box_minmax[i][j] = {corners[0], corners[0]};
528 for (
int l = 1; l < 4; l++) {
529 if (corners[l] > box_minmax[i][j][1]) {
530 box_minmax[i][j][1] = corners[l];
531 }
else if (corners[l] < box_minmax[i][j][0]) {
532 box_minmax[i][j][0] = corners[l];
541 for (
int i = 0; i < fNumSin-1; i++) {
542 for (
int j = 0; j <
fNumDm2-1; j++) {
544 if ((target >= box_minmax[i][j][0]) && (target <= box_minmax[i][j][1])) {
552 for (
int j = 0; j < contour.size(); j++) {
553 sin_contour[
k].push_back(contour[j][0]);
554 dm2_contour[
k].push_back(contour[j][1]);
559 clock_t endcont = clock();
560 clock_t tickscont = endcont - startcont;
561 double timecont = tickscont / (double) CLOCKS_PER_SEC;
563 std::cout <<
" Done in " << timecont <<
"s." << std::endl;
566 std::vector <TGraph*> graphs;
567 for (
int i = 0; i < sin_contour.size(); i++) {
569 graphs.push_back(
new TGraph());
571 for (
int j = 0; j < sin_contour[i].size(); j++) {
572 graphs[i]->SetPoint(j, sin_contour[i][j], dm2_contour[i][j]);
590 TFile* chi2file = TFile::Open(
fOutputFile.c_str(),
"recreate");
591 assert(chi2file && chi2file->IsOpen());
604 sample.fBkgCounts->Write();
610 sample.fSignalCounts->Write();
617 TH1D *hist =
new TH1D(name.c_str(), name.c_str(), sample.fBins.size()-1, &sample.fBins[0]);
618 std::vector<double> oscillated = sample.Oscillate(osc_vals[0], osc_vals[1]);
619 for (
unsigned i = 0; i < oscillated.size(); i++) {
620 hist->SetBinContent(i+1, oscillated[i]);
TH1D * fBkgCounts
Background count Histogram.
process_name opflash particleana ie x
std::vector< double > Background() const
std::vector< std::vector< double > > chisq_diffs
Container for chi2 values.
void Initialize(fhicl::ParameterSet *config)
TMatrixDSym CovarianceMatrix()
void Initialize(fhicl::ParameterSet *config)
void FileCleanup(TTree *eventTree)
std::vector< double > fDistBins
Distance bin limits.
process_name opflashCryoW ana
EventSample(const fhicl::ParameterSet &config)
std::vector< double > Signal() const
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
std::vector< double > sin2theta
std::vector< double > dm2
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
std::vector< std::array< double, 2 > > fSaveOscillations
std::vector< double > fLogDm2Lims
double numu_to_nue(double x, double sin, double dm2)
#define DECLARE_SBN_POSTPROCESSOR(classname)
counts_as<> counts
Number of ADC counts, represented by signed short int.
std::vector< double > fLogSinLims
double NumuOscillate(ROOT::Math::IntegratorOneDim &integrator, double l_min, double l_max, double e_min, double e_max, double dm2, double sinth)
The standard subrun data definition.
void ProcessSubRun(const SubRun *subrun)
The standard event data definition.
std::vector< double > fTrueEBins
True energy bin limits.
std::vector< EventSample > fEventSamples
int fOscType
Oscilaltion type: 0 == None, 1 == numu -> nue, 2 == numu -> numu.
void ProcessEvent(const event::Event *event)
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double fBackgroundRejection
std::string to_string(WindowPattern const &pattern)
double osc_factor_L_integrated(double energy, double l_min, double l_max, double dm2)
void ProcessSubRun(const SubRun *subrun)
TH3D * fSignalCounts
Signal Count Histogram.
double fSelectionEfficiency
void FileCleanup(TTree *eventTree)
std::vector< double > Oscillate(double sinth, double dm2) const
void ProcessEvent(const event::Event *event)
BEGIN_PROLOG could also be cout
std::vector< Interaction > truth
All truth interactions.
double numu_to_numu(double x, double sin, double dm2)