float n3HeSim(int nev_=0, float rfsf_phi_=300, int sev=0) { // commandline option '-var=val' to change any global for (int i=1; i<gApplication->Argc(); ++i) { TString opt(gApplication->Argv(i)); if ((opt[0]=='-' || opt[0]=='+') && opt.Contains("=")) gROOT->ProcessLine(opt=opt.Append(";").Strip(TString::kLeading,'-')); } if (nev_) nev = nev_; if (rfsf_phi_!=0) rfsf_phi=rfsf_phi_/360.; TFile* f = new TFile("/home/siplu/GIT/n3He_Soft/Github/Simulation/data/mcstas.root"); TNtuple* ntp = (TNtuple*)f->Get("mcstas"); // set up ntuple BRANCH(l); BRANCH(pol); BRANCH(p5); BRANCH(p6); BRANCH(t6); BRANCH(x6); BRANCH(y6); BRANCH(vx6); BRANCH(vy6); BRANCH(vz6); float chop[4]; TBranch* b_chop[4]; for (int j=0;j<nch;++j) { b_chop[j]=ntp->GetBranch(vch[j]); ntp->SetBranchAddress(vch[j],&chop[j]); } // precalculate track projections float dwc = lwc/nz; // WC parameters float da = 2./na, a0=-1+da/2; // polar [cos(theta)] integration float db = 2*PI/nb, b0=-PI+db/2; // azimuthal [phi] integration float cxyz[3], &cx=cxyz[0],&cy=cxyz[1],&cz=cxyz[2]; // projection cosines float ccz[NDIV], ccx[NDIV][NDIV], ccy[NDIV][NDIV], as; // cached values float aa=a0; for (int ia=0; ia<na; ++ia, aa+=da) { ccz[ia]=aa; if (ccz[ia]==0) ccz[ia]=1e-11; as=sqrt(1-aa*aa); float bb=b0; for (int ib=0; ib<nb; ++ib, bb+=db) { ccx[ia][ib]=as*cos(bb); if (ccx[ia][ib]==0) ccx[ia][ib]=1e-11; ccy[ia][ib]=as*sin(bb); if (ccy[ia][ib]==0) ccy[ia][ib]=1e-11; } } // cumulative beta distribution for (int i=0;i<nbet;++i) beta_int[i+1]=beta_int[i]+beta_pt[i]; // initialize WC response matrices double n5 = 0; // pre-polarizer neutrons double N[NTOF]={0}; // chopped neutrons at end of SMpol double P2N[NTOF]={0}; // " * P^2 double WN[NTOF]={0}; // captures in 3He target double BN[NTOF][nwc]={{0}}; // N_i = N beta_i = \sum{n_i} ions double GBN[NTOF][nwc]={{0}}; // M_i = N_i gamma_i = \sum{n_i gamma} double D2N[NTOF][nwc][nwc]={{{0}}}; // delta^2 N_ij = covariance double GW[NTOF][nwc]={{0}}; // weight of each element // loop over events, fill "n","p2n" histograms, wc response matrices if (ntp->GetEntries()<nev) nev=ntp->GetEntries(); for (int iev=sev;iev<sev+nev;++iev) { if (verbose && cnt) { // :........:.... if (iev%(50*cnt)==0) cout<<endl<<" :"<<flush; else if (iev%(10*cnt)==0) cout<<":"<<flush; else if (iev%cnt==0) cout<<"."<<flush; } // read variables ntp->GetEntry(iev); hl5.Fill(l,p5*1.4/2*60); n5 += p5; hl6.Fill(l,p6*1.4/2*60); // polarizer float tx = 1; //Transmission b_pol->GetEntry(iev); if (pol!=pol) pol=0; //nan // choppers for (int j=0;j<nch;++j) { float chw = chop[j]-ch_phi[j]; if (chw<0) chw += 360; if (chw>ch_open[j]) { tx=0; break; } } if (tx==0) continue; hlc.Fill(l,p6*1.4/2*60); // RFSF, averaged over spin sequence float t_sf = (t6+(zsf-z6)/vz6)*freq; static const float spin_seq_ave[]={1, -0.5, 0, 0.5, -1, 0.5, 0, -0.5}; if (psf==1 && (t_sf<rfsf_phi || t_sf>rfsf_phi+dsf)) continue; if (t_sf!=0) { if (dsf<0) { pol*= spin_seq_ave[int(fabs(t_sf-rfsf_phi-0.5)+0.5)%8]; pol*=(1-cos(k_rfsf/vz6/(fmod(t_sf-rfsf_phi+10,1)+rfsf_phi)))/2.; } else { if (t_sf<rfsf_phi || t_sf>rfsf_phi+dsf) pol*=psf; } } hls.Fill(l,p6*1.4/2*60); // fill histograms for N,P2N float dtev=(zwc-z6)/vz6, tev=fmod((t6+dtev)*freq, 1); int it((tev*ntof+1)-1); assert(it>=0 && it<ntof); float n = p6 * tx; N [it] += n; P2N[it] += n * pol*pol; // collimator float xx=x6+vx6*(zwc-z6)/vz6; if (xcol>0 && fabs(xx)>xcol/2) continue; float yy=y6+vy6*(zwc-z6)/vz6; if (ycol>0 && fabs(yy)>ycol/2) continue; hlx.Fill(l,p6*1.4/2*60); // simulate ion chamber response float zev=dwc/2.; for (int iz=0; iz<nz; ++iz, zev+=dwc) { dtev=(zev+zwc-z6)/vz6; tev=fmod((t6+dtev)*freq, 1); it = int(tev*ntof+1)-1; assert(it>=0 && it<ntof); float xev=x6+vx6*dtev, yev=y6+vy6*dtev; float rhosig=rho3*ksig*l; // attenuation const and weight float wza = (exp(-rhosig*zev)-exp(-rhosig*(zev+dwc)))*da/2*db/2/PI; for (int ia=0; ia<na; ++ia) { cz=ccz[ia]; for (int ib=0; ib<nb; ++ib) { cx=ccx[ia][ib]; cy=ccy[ia][ib]; float d1=d1r, d2=d2r, d1t,d2t; // ionization range // restrict ionization to active volume of wc if (cz>0) d1t=(z1w-zev)/cz, d2t=(z2w-zev)/cz; else d1t=(z2w-zev)/cz, d2t=(z1w-zev)/cz; if (d1<d1t) d1=d1t; if (d2>d2t) d2=d2t; if (cx>0) d1t=(x1w-xev)/cx, d2t=(x2w-xev)/cx; else d1t=(x2w-xev)/cx, d2t=(x1w-xev)/cx; if (d1<d1t) d1=d1t; if (d2>d2t) d2=d2t; if (cy>0) d1t=(y1w-yev)/cy, d2t=(y2w-yev)/cy; else d1t=(y2w-yev)/cy, d2t=(y1w-yev)/cy; if (d1<d1t) d1=d1t; if (d2>d2t) d2=d2t; if (d2<d1) continue; // not in active volume // iterate over ionized cells float beta1, beta0=beta_fn(d1); float wz=(z0w-zev)/cz, dwz=dzw/cz; int jz((d1-wz)/dwz), djz=1; if (jz==nwz) --jz; wz+=dwz*jz; if (cz>0) wz+=dwz; else dwz*=-1, djz*=-1; float wx=(x0w-xev)/cx, dwx=dxw/cx; int jx((d1-wx)/dwx), djx=1; if (jx==nwx) --jx; wx+=dwx*jx; if (cx>0) wx+=dwx; else dwx*=-1, djx*=-1; int k=0; assert(0<=jz&&jz<nwz && 0<=jx&&jx<nwx); while (0<=jz&&jz<nwz && 0<=jx&&jx<nwx) { kzx[k] = jz*nwx + jx; if (d2<=wz && d2<=wx) { kbeta[k++]=beta_fn(d2)-beta0; break; } if (wz<wx) { beta1=beta_fn(wz); jz+=djz; d1=wz; wz+=dwz; } else { beta1=beta_fn(wx); jx+=djx; d1=wx; wx+=dwx; } kbeta[k++]=beta1-beta0; beta0=beta1; } // tabulate ion response WN[it] += n*wza; for (int i=0;i<k;++i) { float ni= n*wza*kbeta[i]; BN [it][kzx[i]] += ni; GBN[it][kzx[i]] += ni*cxyz[geom_xyz]; for (int j=0;j<k;++j) { D2N[it][kzx[i]][kzx[j]] += ni*kbeta[j]; } } } } } } f->Close(); // calculate FOM=p2n, projection; draw both double N_tot=0, P2N_tot=0, WN_tot=0, xd2a_tot=0; for (int it=0;it<ntof;++it) { TMatrixDSym mat(nwc, &**D2N[it]); if (verbose>3 && ntof==1) { cout<<"\n delta^2 N_ij :\n"; mat.Print(); } // for (int i=0;i<nwc;++i) for (int j=0;j<nwc;++j) if (i!=j) mat(i,j)=0; mat.Invert(); if (verbose>3 && ntof==1) { cout<<"\n delta^-2 N_ij :\n"; mat.Print(); } double xd2a=0; for (int i=0;i<nwc;++i) { for (int j=0;j<nwc;++j) { GW[it][i] += GBN[it][i]*GBN[it][j]*mat(i,j); } xd2a += GW[it][i]; } N_tot += N[it]; P2N_tot+= P2N[it]; WN_tot += WN[it]; xd2a_tot += xd2a; if (verbose > 2) { printf("\n beta_i:"); for (int i=0;i<nwc;++i) { if (!(i%nwx)) printf("\n "); printf(" %9.5g",BN[it][i]/N[it]); } printf("\n\n gamma_i:"); for (int i=0;i<nwc;++i) { if (!(i%nwx)) printf("\n "); printf(" %9.5g",GBN[it][i]/BN[it][i]); } printf("\n\n weight_i:"); for (int i=0;i<nwc;++i) { if (!(i%nwx)) printf("\n "); printf(" %9.5g",GW[it][i]); } printf("\n\n"); } if (verbose > 4) { printf("\n\n beta_i:"); for (int j=0;j<nwc;++j) { printf(" %9.5g",BN[it][j]/N[it]); } printf("\n\n beta_ij:"); for (int i=0;i<nwc;++i) { printf("\n "); for (int j=0;j<nwc;++j) { printf(" %9.5g", D2N[it][i][j]/N[it]); } } } if (verbose>1 && ntof>1) { cout<<" N = "<< N[it] <<endl; cout<<" <P^2> = "<< P2N[it] / N[it] <<endl; cout<<" <W> = "<< WN[it] / N[it] <<endl; cout<<" delta^-2 A = "<< xd2a*P2N[it]/N[it] <<endl; cout<<" sigma_d = "<< sqrt(N[it] / xd2a) <<endl<<endl<<endl; } } cout<<"All TOF bins combined"<<endl; cout<<" N0 = "<< n5 <<endl; cout<<" N = "<< N_tot <<endl; cout<<" <P^2> = "<< P2N_tot/N_tot <<endl; cout<<" <W> = "<< WN_tot / N_tot <<endl; cout<<" delta^-2 A = "<< xd2a_tot*P2N_tot/N_tot <<endl; cout<<" sigma_d = "<< sqrt(N_tot / xd2a_tot) <<endl; return sqrt(N_tot / xd2a_tot); }