6 #include "TObjString.h" 7 #include "TTimeStamp.h" 11 #include "EnvironmentVariable.h" 12 #include "Math/WrappedTF1.h" 13 #include "Math/GaussIntegrator.h" 15 #include "blazars/fava.h" 17 #include "icemc_random.h" 22 SourceModel::SourceModel(
const char * n)
28 average_nonzero_flux= -1;
31 SourceModel::~SourceModel()
33 for (
unsigned i = 0; i < sources.size(); i++)
delete sources[i];
38 static double luminosity_distance(
double z)
40 static TF1 * f_comoving = 0;
43 f_comoving =
new TF1(
"comoving_distance",
"[0] / sqrt([1]*(1+x)^4 + [2] * (1+x)^3 + [3] * (1+x)^2 + [4])", 0,10);
44 f_comoving->SetParameters(67.74, 5e-5, 0.3089, 0, 0.6911);
47 double d_M = f_comoving->Integral(0,z);
53 const double txs_index = 2;
54 const double txs_norm = 2.2e-8;
55 const double txs_E0 = 100e3;
56 const double txs_flux = 3.8;
57 const double txs_z = 0.3365;
58 const double txs_D = luminosity_distance(txs_z);
62 const double m77_index = 3.16;
67 const double gamma_index = 2;
69 double SourceModel::Restriction::fromString(
const char * the_time)
71 printf(
"PARSING \"%s\"\n",the_time);
73 if(strcasestr(the_time,
"A4_MIN"))
77 else if(strcasestr(the_time,
"A3_MIN"))
81 else if(strcasestr(the_time,
"A4_MAX"))
85 else if(strcasestr(the_time,
"A3_MAX"))
89 else if(strcasestr(the_time,
"MAX"))
94 return atof(the_time);
102 if (!key || !strcasecmp(key,
"NONE"))
return NULL;
107 TObjArray * tokens = str.Tokenize(
"+");
110 for (
int i =0; i < tokens->GetEntries(); i++)
112 TObjString * tok = (TObjString*) tokens->At(i);
114 TString stripped( tok->String().Strip( TString::kBoth));
117 if (stripped ==
"TXS")
120 double txs_ra = 77.3582;
121 double txs_dec = 5.69314;
128 else if (stripped.BeginsWith(
"M77"))
131 double index = m77_index;
132 const char * index_string = strcasestr(stripped.Data(),
"INDEX=");
135 sscanf(index_string,
"HOURS=%lf%*s", &index);
143 else if(stripped==
"A3SN")
145 TFile f(
"./supernovae/data/supernovaA3.root");
146 TTree *tree = (TTree*) f.Get(
"sn");
147 std::string *objName =
new std::string;
148 std::string *objType =
new std::string;
153 tree->SetBranchAddress(
"ra",&ra);
154 tree->SetBranchAddress(
"dec",&dec);
155 tree->SetBranchAddress(
"tdiscovery",&tdiscovery);
156 tree->SetBranchAddress(
"texplode",&texplode);
157 tree->SetBranchAddress(
"name",&objName);
158 tree->SetBranchAddress(
"type",&objType);
159 int two_weeks = 24*3600*14;
161 for (
int i = 0; i < tree->GetEntries(); i++)
164 if( abs(dec)>r.maxDec){
continue;}
174 else if(stripped==
"SN")
176 TFile *file =
new TFile(
"./supernovae/data/supernovaeTNS.root");
177 TTree *tree = (TTree*) file->Get(
"tnsTree");
181 std::string *objName =
new std::string;
182 std::string *fullObjType =
new std::string;
183 std::string *objSubtype =
new std::string;
184 int discoveryUnixTime = 0;
186 tree->SetBranchAddress(
"ra",&ra);
187 tree->SetBranchAddress(
"dec",&dec);
188 tree->SetBranchAddress(
"name",&objName);
189 tree->SetBranchAddress(
"fullObjType",&fullObjType);
190 tree->SetBranchAddress(
"objSubtype",&objSubtype);
191 tree->SetBranchAddress(
"discoveryUnixTime",&discoveryUnixTime);
193 int two_weeks = 24*3600*14;
195 for (
unsigned int i = 0; i < tree->GetEntries(); i++)
204 if( (discoveryUnixTime < r.whichStartTime) || (discoveryUnixTime > r.whichEndTime + two_weeks) ){
continue;}
206 if( abs(dec)>r.maxDec){
continue;}
208 if(strcasecmp(r.whichSources,
"All"))
211 if(strcasestr(r.whichSources, objName->c_str()))
213 std::cout <<
"Using the specified source: " << objName << std::endl;
219 if(strcasecmp(r.whichSubtype,
"All"))
221 if(strcasestr(r.whichSubtype,objSubtype->c_str()))
235 else if (stripped.BeginsWith(
"GRB"))
237 TFile *file =
new TFile(
"./GRBs/data/GRBIceCube.root");
238 TTree *tree = (TTree*) file->Get(
"iceCubeTree");
242 std::string *objName =
new std::string;
243 int unixTriggerTime = 0;
244 float t90, fluence, redshift;
246 tree->SetBranchAddress(
"RA",&RA);
247 tree->SetBranchAddress(
"dec",&dec);
248 tree->SetBranchAddress(
"name",&objName);
249 tree->SetBranchAddress(
"unixTriggerTime",&unixTriggerTime);
250 tree->SetBranchAddress(
"T90",&t90);
251 tree->SetBranchAddress(
"fluence",&fluence);
252 tree->SetBranchAddress(
"redshift",&redshift);
254 for (
unsigned int i = 0; i < tree->GetEntries(); i++)
258 if (fluence < 0) fluence = 1e-6;
262 if( (unixTriggerTime < r.whichStartTime) || (unixTriggerTime > r.whichEndTime) ){
continue;}
264 if( abs(dec)>r.maxDec){
continue;}
266 printf(
"%d\n", unixTriggerTime);
269 if(strcasecmp(r.whichSources,
"All"))
272 if(strcasestr(r.whichSources,objName->c_str()))
274 std::cout <<
"Using the specified source: " << objName << std::endl;
280 bool modelCalculation =
true;
281 double energyCutoff = 1e10;
282 if(modelCalculation==
true)
286 double omegaRad = 9.236e-5;
287 double omegaM = 0.315;
288 double omegaLambda = 0.679;
289 double H0 = 67.4 * pow(10,3);
290 double c = 299792458;
291 double EGammaIso = 0.;
293 double MpcToCm = 3.08e+24;
299 double lorentzFactor = 300.;
305 double shockLorentzFactor = 0.;
306 double energyCGamma = 0.;
308 double energyBreakNeutrinoAG = 0.;
309 double shockRadius = 0.;
310 double massProton = 0.0015;
311 double magFieldShock = 0.;
312 double maxShockNuE = 0.;
316 if(t90==-999){t90 = 20;}
318 if(redshift==-999){redshift = 2;}
320 if(fluence==-999){fluence=1e-6;}
325 TF1 Ez(
"E(z)",
"1/(pow([0] * pow((1+x),3) + [1] + [2] * pow((1+x),4),0.5))", 0, redshift);
327 Ez.SetParameter(0,omegaM); Ez.SetParName(0,
"omegaM");
328 Ez.SetParameter(1,omegaLambda); Ez.SetParName(1,
"omegaLambda");
329 Ez.SetParameter(2,omegaRad); Ez.SetParName(2,
"omegaRad");
330 ROOT::Math::WrappedTF1 wEz(Ez);
331 ROOT::Math::GaussIntegrator ig;
333 ig.SetRelTolerance(0.001);
334 double integral = ig.Integral(0, redshift);
337 dL = (1+redshift) * c/H0 * integral;
340 EGammaIso = 4 * TMath::Pi() * dL*dL * fluence * 1/(1+redshift);
341 EGammaIso*=pow(MpcToCm,2);
348 EKinIso = EGammaIso/eE;
351 shockRadius = pow(((3*EKinIso)/(4*TMath::Pi() * nEx * massProton * c*c * lorentzFactor*lorentzFactor)),(1./3.));
355 std::cout <<
"Afterglow shock radius < burst radius. Something might be wrong." << std::endl;
359 magFieldShock = pow(8 * TMath::Pi() * eB * nEx * massProton,0.5);
361 shockLorentzFactor = 195 * pow(((EKinIso)/(pow(10,54))),0.125) * pow(t90/10,-0.375) * pow(nEx/1.,-0.125);
364 energyCGamma = 0.4 * pow(((EKinIso)/(pow(10,54))),(-25./24.)) * pow(((lorentzFactor)/(300)),(4./3.)) * pow(((t90)/(10)),(9./8.)) * pow(((nEx)/(1)),(-11./24.));
373 energyBreakNeutrinoAG = 0.015 * shockLorentzFactor * 1/(1+redshift) * pow(energyCGamma,-1);
375 maxShockNuE = fPiAG/(4*(1+redshift)) * eE * shockLorentzFactor * magFieldShock * shockRadius;
378 if(maxShockNuE > energyBreakNeutrinoAG)
382 else if(maxShockNuE < 1e9)
388 maxShockNuE = energyBreakNeutrinoAG+energyBreakNeutrinoAG*0.01;
391 energyCutoff = maxShockNuE;
395 double afterglow_hrs = 1;
397 const char * hours_string = strcasestr(stripped.Data(),
"HOURS=");
400 sscanf(hours_string,
"HOURS=%lf%*s", &afterglow_hrs);
401 printf(
"AFTERGLOW HOURS is %f\n", afterglow_hrs);
405 if (strcasestr(stripped.Data(),
"AFTERGLOW") )
409 unixTriggerTime + 3600*afterglow_hrs,1.5,
410 fluence,1e9, energyCutoff)
414 else if (strcasestr(stripped.Data(),
"PROMPT") )
419 unixTriggerTime + t90,4,
431 unixTriggerTime + 3600*afterglow_hrs,1.5,
440 else if (stripped.BeginsWith(
"FAVA"))
444 bool flux_weighted = strcasestr(stripped.Data(),
"FLUX");
445 bool z_weighted = strcasestr(stripped.Data(),
"REDSHIFT");
449 TFile ffava(Form(
"%s/blazars/fava.root", dir));
450 TTree * fava_tree = (TTree*) ffava.Get(
"fava");
453 fava_tree->SetBranchAddress(
"fava",&fava);
455 for (
int i = 0; i < fava_tree->GetEntries(); i++)
457 fava_tree->GetEntry(i);
460 if( (fava->unix_tmax < r.whichStartTime) || (fava->unix_tmin > r.whichEndTime) ){
continue;}
462 const char * fava_name = fava->association.GetString().Data();
465 if(strcasestr(fava_name,
"None"))
472 if(strcasecmp(r.whichSources,
"All"))
475 if(strcasestr(r.whichSources,fava_name))
477 std::cout <<
"Using the specified source: " << fava_name << std::endl;
492 if (fava->source_class.GetString() ==
"bcu" || fava->source_class.GetString() ==
"fsrq" || fava->source_class.GetString() ==
"bll")
497 txs_norm * (flux_weighted ? fava->he_flux / txs_flux : z_weighted ? txs_flux * pow(txs_D/luminosity_distance(fava->z),2): 1), txs_E0))
507 std::cout <<
"----------------------" << std::endl;
509 if (!m->getNSources())
511 fprintf(stderr,
"WARNING: no sources added for key %s\n", key);
517 std::cout <<
"Sources added: " << m->getNSources() << std::endl;
523 TH1 * SourceModel::estimateFlux(
double tmin,
double tmax,
double Emin,
double Emax,
int nbins,
int N)
525 double from = log10(Emin);
526 double to = log10(Emax);
528 TH1D * spectrum =
new TH1D(
"spec", name, nbins, from, to);
529 spectrum->SetDirectory(0);
530 spectrum->GetXaxis()->SetTitle(
"log10 (E GeV)");
531 TRandom * rng = getRNG(RNG_SOURCE);
532 for (
int i = 0; i < N; i++)
534 double t = rng->Uniform(tmin,tmax);
535 for (
unsigned j = 0; j < sources.size(); j++)
538 for (
int E = 1; E<= nbins; E++)
540 double l = TMath::Power(10,spectrum->GetBinLowEdge(E));
541 double h = TMath::Power(10,spectrum->GetBinLowEdge(E) + spectrum->GetBinWidth(E));
542 spectrum->Fill(spectrum->GetBinCenter(E), sources[j]->getFlux()->getFluxBetween(l,h,t));
547 spectrum->Scale(1./N);
557 for (
unsigned i = 0; i < sources.size(); i++)
559 sources[i]->getFlux()->getFluxTimeChanges(changes);
563 std::sort(changes->begin(), changes->end());
564 std::vector<double>::iterator it = std::unique(changes->begin(),changes->end());
565 changes->resize(std::distance(changes->begin(),it));
570 if (!sources.size())
return -1;
572 bool fixedEnergy = minE==maxE;
573 if (fixedEnergy) nuE = minE;
576 double total_flux = 0 ;
577 std::vector<double> fluxes(sources.size());
579 for (
unsigned i = 0; i < sources.size(); i++)
581 double f = fixedEnergy ? sources[i]->getFlux()->getFlux(nuE,t) : sources[i]->getFlux()->getFluxBetween(minE,maxE,t);
583 fluxes[i] = total_flux;
586 TRandom * rng = getRNG(RNG_SOURCE);
587 double random = rng->Uniform(0, total_flux);
588 unsigned index = std::upper_bound(fluxes.begin(), fluxes.end(), random) - fluxes.begin();
599 const Source * which = sources[index];
604 if (nudir) *nudir = which->getDirection(t);
606 if (!fixedEnergy) nuE = which->getFlux()->pickEnergy(minE,maxE,t,rng);
612 Source::Source(
const char * nm,
double ra,
double dc,
SourceFlux * f)
613 : name(nm), flux(f) , RA(ra), dec(dc*TMath::DegToRad())
617 Vector Source::getDirection(
double t)
const 620 #if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) 621 std::cerr <<
"ROOT 5 doesn't have AsLMST. Returning nonsense." << std::endl;
626 int nsecs = 1e9 *(t-secs);
627 TTimeStamp ts(secs, nsecs);
628 double lst = ts.AsLMST(-90);
630 h *= (TMath::Pi()/12);
631 return Vector(cos(h) * cos(dec), sin(h) * cos(dec), sin(dec));
636 ConstantExponentialSourceFlux::ConstantExponentialSourceFlux(
double e,
double norm,
double normE)
637 : gamma(e) , f(
"f",
"[0] * x^-[1]",1e9,1e12)
640 A = norm * TMath::Power(normE,gamma);
641 f.SetParameters(A,gamma);
644 double ConstantExponentialSourceFlux::pickEnergy(
double Emin,
double Emax,
double t, TRandom * rng)
const 647 TRandom * old = gRandom;
649 if (Emin == Emax)
return Emin;
652 if (f.GetXmin() != Emin || f.GetXmax() !=Emax) f.SetRange(Emin,Emax);
654 double E = f.GetRandom();
660 TimeWindowedExponentialSourceFlux::TimeWindowedExponentialSourceFlux(
double t0,
double t1,
double e,
double norm,
double normE,
double cutoff)
661 : gamma(e) , f(
"f",
"[0] * x^-[1]",1e9,cutoff ? cutoff : 1e12) , t0(t0), t1(t1) , cutoff(cutoff)
664 A = norm * TMath::Power(normE,gamma);
665 f.SetParameters(A,gamma);
668 double TimeWindowedExponentialSourceFlux::pickEnergy(
double Emin,
double Emax,
double t, TRandom * rng)
const 670 if (t < t0 || t > t1)
return 0;
671 TRandom * old = gRandom;
673 if (cutoff && Emax > cutoff) Emax = cutoff;
676 if (f.GetXmin() != Emin || f.GetXmax() !=Emax) f.SetRange(Emin,Emax);
678 double E = f.GetRandom();
688 average_nonzero_flux = 0;
690 per_source_average_flux.clear();
691 per_source_average_nonzero_flux.clear();
692 per_source_average_flux.resize(sources.size());
693 per_source_average_nonzero_flux.resize(sources.size());
694 std::vector<int> Nnonzero_per_source(sources.size());
700 TRandom * rng = getRNG(RNG_SOURCE);
701 for (
int i =0; i < N; i++)
703 double t = rng->Uniform(t0,t1);
705 for (
unsigned j = 0; j < sources.size(); j++)
707 double dFlux = minE == maxE ? sources[j]->getFlux()->getFlux(minE, t) : sources[j]->getFlux()->getFluxBetween(weight_Emin,weight_Emax,t);
710 average_flux += dFlux/N;
711 per_source_average_flux[j]+=dFlux/N;
712 average_nonzero_flux += dFlux;
716 Nnonzero_per_source[j]++;
717 per_source_average_nonzero_flux[j]+= dFlux;
726 for (
unsigned j = 0; j < sources.size(); j++)
728 if (per_source_average_nonzero_flux[j]) per_source_average_nonzero_flux[j] /= Nnonzero_per_source[j];
731 if (average_nonzero_flux) average_nonzero_flux /= Nnonzero;
732 printf(
"Set up weights: average flux is %g (average non-zero flux: %g)\n", average_flux, average_nonzero_flux);
735 double SourceModel::getPerSourceTimeWeight(
double t,
int i,
bool use_average_nonzero_flux)
const 737 double weight = weight_Emin == weight_Emax ? sources[i]->getFlux()->getFlux(weight_Emin,t)
738 : sources[i]->getFlux()->getFluxBetween(weight_Emin,weight_Emax,t);
740 return weight / (use_average_nonzero_flux ? per_source_average_nonzero_flux[i] : per_source_average_flux[i]);
743 double SourceModel::getTimeWeight(
double t,
bool use_average_nonzero_flux)
const 746 if (average_flux < 0)
748 if (nnag++ < 100) fprintf(stderr,
"WARNING: setUpWeights() hasn't been called yet. Will return crazy value!\n");
751 for (
unsigned i = 0; i < sources.size(); i++)
753 weight += weight_Emin == weight_Emax ? sources[i]->getFlux()->getFlux(weight_Emin,t) : sources[i]->getFlux()->getFluxBetween(weight_Emin,weight_Emax,t);
755 return weight / (use_average_nonzero_flux ? average_nonzero_flux : average_flux);
void computeFluxTimeChanges(std::vector< double > *changes) const
int getDirectionAndEnergy(Vector *nudir, double t, double &nuE, double minE=1e9, double maxE=1e12)
const char * ICEMC_SRC_DIR()
static SourceModel * getSourceModel(const char *key, Restriction r=Restriction())
void addSource(Source *source)
This class represents a three-vector. Operators are overloaded to provide for the familiar operations...
void setUpWeights(double t0, double t1, double minE=1e9, double maxE=1e12, int N=1e6)