Example #1
0
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);
}