<!DOCTYPE HTML PUBLIC "-// IETF/DTD HTML 2.0// EN">
<html>
<!--                                             -->
<!-- Author: ROOT team (rootdev@hpsalo.cern.ch)  -->
<!--                                             -->
<!--   Date: Tue Apr  6 15:52:00 1999            -->
<!--                                             -->
<head>
<title>CalRecon - source file</title>
<link rev=made href="mailto:rootdev@root.cern.ch">
<meta name="rating" content="General">
<meta name="objecttype" content="Manual">
<meta name="keywords" content="software development, oo, object oriented, unix, x11, motif, windows nt, c++, html, rene brun, fons rademakers">
<meta name="description" content="ROOT - An Object Oriented Framework For Large Scale Data Analysis.">
</head>
<body BGCOLOR="#ffffff" LINK="#0000ff" VLINK="#551a8b" ALINK="#ff0000" TEXT="#000000">
<a name="TopOfPage"></a>
<pre>
<b>// $Header: <a href=".././CalRecon.html">CalRecon</a>.cxx $</b>

#include "<a href="../CalRecon.h">CalRecon.h</a>"
#include "<a href="../CalSmeared.h">CalSmeared.h</a>"

#define  false  0
#define  true   1

#define ELEC_TYPE    11  
#define GAMMA_TYPE 22   
#define PIPLUS_TYPE 211 
#define K0SHORT_TYPE 310
#define K0LONG_TYPE  130
#define KPLUS_TYPE 321 
#define PROTON_TYPE 2212
#define NEUTRON_TYPE 2112
#define LAMBDA_TYPE 3122

#define NSMEARABLE  9

#define PIZERO_TYPE 111     // not included among the smearables

#define SMEARABLE_NOT  0
#define SMEARABLE_EM   1
#define SMEARABLE_HAD  2

<b>//______________________________________________________________________</b>
<b>//                                                                       </b>
<b>// <a href=".././CalRecon.html">CalRecon</a></b>
<b>//                                                                </b>
<b>// <a href=".././CalRecon.html">CalRecon</a> is the over-all manager for Fast MC calorimetry.  It must</b>
<b>// be instantiated for each detector (or change to smearing parameters)</b>
<b>// but need only be cleared between events belonging to the same</b>
<b>// detector</b>

ClassImp(<a href=".././CalRecon.html">CalRecon</a>)   

<a name="CalRecon:CalRecon"> </a><a href=".././CalRecon.html#CalRecon:CalRecon">CalRecon::CalRecon</a>(const <a href="http://root.cern.ch/root/html/TString.html">TString</a>&amp; name)  { 
<b>  // Constructor.   Primary job is to assemble various parameters</b>
<b>  // describing detector geometry and resolution.</b>

  <a href="../ListOfTypes.html#Int_t">Int_t</a> ok;
  ok = <a href="#CalRecon:GetDetector">GetDetector</a>(name);
  if (ok) {
<b>    //  InitSmearPar();</b>
    <a href=".././CalRecon.html#CalRecon:smears">smears</a> = new <a href="http://root.cern.ch/root/html/TObjArray.html">TObjArray</a>(10);
  }
  else { // make it clear we have no detector
    <a href=".././CalRecon.html#CalRecon:nVolumes">nVolumes</a> = 0;
    <a href=".././CalRecon.html#CalRecon:pInnerVolume">pInnerVolume</a> = 0;
    <a href=".././CalRecon.html#CalRecon:pVolumes">pVolumes</a> = 0;
  }
}
      
<b>//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</b>
<a name="CalRecon:cleanup"> </a><a href="../ListOfTypes.html#void">void</a> <a href=".././CalRecon.html#CalRecon:cleanup">CalRecon::cleanup</a>() {
<b>  // Get rid of allocated memory, obsolete pointers.</b>

<b>  // Get rid of reference to old <a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a></b>
  <a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a> = 0;

<b>  // Get rid of old <a href=".././CalRecon.html#CalRecon:smears">smears</a> if any</b>
  <a href=".././CalRecon.html#CalRecon:smears">smears</a>-&gt;<a href="http://root.cern.ch/root/html/TObjArray.html#TObjArray:Delete">Delete</a>(0);
  
};

<a name="CalRecon:doit"> </a><a href="../ListOfTypes.html#void">void</a> <a href=".././CalRecon.html#CalRecon:doit">CalRecon::doit</a>(<a href="http://root.cern.ch/root/html/Event.html">Event</a>* event) {
<b>  // Process an event.  For each MC particle, check to see whether it's</b>
<b>  // "smearable".  If so, propagate, then smear energy and transverse</b>
<b>  // position.  </b>

  <a href=".././SmearTraj.html">SmearTraj</a>  traj;
  <a href="../ListOfTypes.html#Bool_t">Bool_t</a>     ok;

  <a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a> = event-&gt;<a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a>();
  <a href=".././CalRecon.html#CalRecon:nPart">nPart</a> = <a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a>-&gt;<a href="http://root.cern.ch/root/html/TObjArray.html#TObjArray:GetLast">GetLast</a>() + 1;

  if (!<a href=".././CalRecon.html#CalRecon:nVolumes">nVolumes</a>) return;  // no detector
  
  for (<a href="../ListOfTypes.html#Int_t">Int_t</a> ix = 0; ix &lt; <a href=".././CalRecon.html#CalRecon:nPart">nPart</a>; ix++) { // Process particle with index ix.
    
    <a href="http://root.cern.ch/root/html/McPart.html">McPart</a>*       pPart = (<a href="http://root.cern.ch/root/html/McPart.html">McPart</a>*) (*<a href=".././CalRecon.html#CalRecon:MCparticles">MCparticles</a>)[ix];
    <a href=".././CalSmeared.html">CalSmeared</a>*   pSmeared;
    <a href="../ListOfTypes.html#Int_t">Int_t</a>         canSmear;

    if (canSmear = <a href="#CalRecon:Smearable">Smearable</a>(pPart)) {
      <a href="../ListOfTypes.html#Bool_t">Bool_t</a> hadron = (canSmear == SMEARABLE_HAD);
      <a href=".././SmearVolume.html">SmearVolume</a> *pCur;
      traj.SetParticle(pPart, ix);
      if (pCur = <a href="#CalRecon:Swim">Swim</a>(&amp;traj, hadron)) {
	pSmeared = new <a href=".././CalSmeared.html">CalSmeared</a>(traj, hadron, pCur-&gt;pFuzz, <a href=".././CalRecon.html#CalRecon:pRand">pRand</a>); 
    
        <a href=".././CalRecon.html#CalRecon:smears">smears</a>-&gt;<a href="http://root.cern.ch/root/html/TObjArray.html#TObjArray:Add">Add</a>(pSmeared);
      }
    }

<b>    // Ultimately may have another stage where distances between first-pass</b>
<b>    // <a href=".././CalRecon.html#CalRecon:smears">smears</a> are examined to see if any are close enough (w.r.t. supplied</b>
<b>    // parameters) to be combined into a single smear</b>
  }
};


<b>//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</b>
<a name="CalRecon:spew"> </a><a href="../ListOfTypes.html#void">void</a> <a href=".././CalRecon.html#CalRecon:spew">CalRecon::spew</a>(FILE* ofile) const
{
<b>  // Output standard cluster quantities to ascii file.</b>

  if (!<a href=".././CalRecon.html#CalRecon:nVolumes">nVolumes</a>) return;  // no detector

  <a href="../ListOfTypes.html#Int_t">Int_t</a>  nSmear = <a href=".././CalRecon.html#CalRecon:smears">smears</a>-&gt;<a href="http://root.cern.ch/root/html/TObjArray.html#TObjArray:GetLast">GetLast</a>() + 1; 
  fprintf(ofile, "Clusters n %i n", nSmear);
<b>  //  fprintf(ofile, "%d MC particles produced %d smeared clustersn", </b>
<b>  //	  <a href=".././CalRecon.html#CalRecon:nPart">nPart</a>, nSmear);</b>
  for (<a href="../ListOfTypes.html#Int_t">Int_t</a> iSmear = 0; iSmear &lt; nSmear; iSmear++) {
    <a href=".././CalSmeared.html">CalSmeared</a>* pSmear = (<a href=".././CalSmeared.html">CalSmeared</a> *) (*<a href=".././CalRecon.html#CalRecon:smears">smears</a>)[iSmear];
    pSmear-&gt;<a href="#CalRecon:spew">spew</a>(ofile);
  }
  fprintf(ofile, "endn");
}

#define VERY_SMALL 0.0000001
#define MCSTAT_FINALSTATE  1
<a name="CalRecon:Smearable"> </a>Int_t CalRecon::Smearable(McPart* pPart) {
<b>  // Check a) that we have a final-state particle b) particle type.  </b>
<b>  // Must be electron/positron, photon, or an acceptable hadron. </b>
<b>  // c) energy.  Must be non-negligible.</b>

  static <a href="../ListOfTypes.html#Int_t">Int_t</a> willSmear[NSMEARABLE] = {
    ELEC_TYPE,
    GAMMA_TYPE,
    PIPLUS_TYPE,
<b>    //    PIZERO_TYPE,</b>
    K0SHORT_TYPE,
    K0LONG_TYPE,
    KPLUS_TYPE,
    PROTON_TYPE,
    NEUTRON_TYPE,
    LAMBDA_TYPE};

  <a href="../ListOfTypes.html#Bool_t">Bool_t</a> ok = false;

<b>  // Check status</b>
  <a href="../ListOfTypes.html#Int_t">Int_t</a> mcStat = pPart-&gt;GetStatus();
  if (mcStat != MCSTAT_FINALSTATE) return SMEARABLE_NOT;

  <a href="../ListOfTypes.html#Int_t">Int_t</a> partType = pPart-&gt;GetType();
  if (partType &lt; 0) {
    partType = - partType;
  }

  for (<a href="../ListOfTypes.html#int">int</a> ix = 0; ix &lt; NSMEARABLE; ix++) {
    if (partType == willSmear[ix]) {
      ok = true;
      break;
    }
  }
  if (!ok) return SMEARABLE_NOT;

<b>  // Energy is very small -- forget it</b>
  <a href="../ListOfTypes.html#Float_t">Float_t</a>* iniMom = pPart-&gt;GetMomentum();
  if (*(iniMom + 3)  &lt; VERY_SMALL) return SMEARABLE_NOT;

  return  ((partType == ELEC_TYPE) || (partType == GAMMA_TYPE)) ?
    SMEARABLE_EM  : SMEARABLE_HAD;
}

<a name="CalRecon:GetDetector"> </a><a href="../ListOfTypes.html#Int_t">Int_t</a> <a href=".././CalRecon.html#CalRecon:GetDetector">CalRecon::GetDetector</a>(const <a href="http://root.cern.ch/root/html/TString.html">TString</a>&amp; name) {
<b>  // Somehow get access to needed detector parameters.  For now, use the</b>
<b>  // name to identify a set of parameters.  Could also use it to identify</b>
<b>  // a file, or to just ask (from some parameter server class) for information</b>
<b>  // about the "ambient" detector, if any.</b>
<b>  //</b>
<b>  // Result of this call is to initialize the following fields in <a href=".././CalRecon.html">CalRecon</a>:</b>
<b>  //       nBarrel   pBarrels</b>
<b>  //       nEndcap   pEndcaps</b>
<b>  // so that at the end have a list of pointers to barrels, arranged in</b>
<b>  // order of increasing R, and a list of endcap in order of increasing z</b>
  
  <a href=".././CalRecon.html#CalRecon:pRand">pRand</a> = new <a href="http://root.cern.ch/root/html/TRandom.html">TRandom</a>();

  if (name.CompareTo("Small") == 0)   <a href="#CalRecon:GetSmall">GetSmall</a>();
  else if (name.CompareTo("Large") == 0) <a href="#CalRecon:GetLarge">GetLarge</a>();
  else {
    printf("Unsupported detectorn");
    return 0;
  }

  return 1;
}

<a name="CalRecon:Swim"> </a><a href=".././SmearVolume.html">SmearVolume</a>*  <a href=".././CalRecon.html#CalRecon:Swim">CalRecon::Swim</a>(<a href=".././SmearTraj.html">SmearTraj</a>* pTraj, <a href="../ListOfTypes.html#Bool_t">Bool_t</a> hadron) {
<b>  // Swim particle with initial conditions described in pTraj through</b>
<b>  // the detector.  Return true if particle showers in the detector</b>
<b>  // (where the coil counts as part of the detector)</b>

  <a href=".././SmearTraj.html#SmearTraj:PropagateRet">SmearTraj::PropagateRet</a> status;
  <a href="../ListOfTypes.html#Int_t">Int_t</a>                   charge = pTraj-&gt;GetCharge();
  <a href=".././SmearVolume.html">SmearVolume</a>*            pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) <a href=".././CalRecon.html#CalRecon:pInnerVolume">pInnerVolume</a>;
  <a href="../ListOfTypes.html#Double_t">Double_t</a>                decrS;              // measured in cm
  <a href="../ListOfTypes.html#Double_t">Double_t</a>      totalPath, remPath; // measured in interaction/rad len
  <a href="../ListOfTypes.html#Double_t">Double_t</a>      decrPath;
  <a href="../ListOfTypes.html#Double_t">Double_t</a>*     pPos;
  <a href="../ListOfTypes.html#Double_t">Double_t</a>*     pMom;
  <a href=".././SmearVolume.html">SmearVolume</a>*  pNextVolume;

  <a href="../ListOfTypes.html#int">int</a>           nVolume = 0;       // debug info
<b>  // traj has been initialized with position, momentum, charge</b>

<b>  // First swim through empty central volume</b>
  if ((pCur-&gt;field != 0.0) &amp;&amp; (charge != 0)) { // helix
    status = pTraj-&gt;HelixToCyl(pCur, &amp;decrS);
  }
  else {  // straight line
    status = pTraj-&gt;LineToCyl(pCur, &amp;decrS);
  }
  if ((status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_NONE">SmearTraj::INTERSECT_NONE</a>) ||
      (status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ERROR">SmearTraj::INTERSECT_ERROR</a>)   ) return 0;

<b>  // Check that we didn't exit to the air volume next to the beampipe.</b>
  pPos = pTraj-&gt;GetNewPos();
  if ((status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ZPLUS">SmearTraj::INTERSECT_ZPLUS</a>) || 
      (status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ZMINUS">SmearTraj::INTERSECT_ZMINUS</a>)) {
    <a href="../ListOfTypes.html#Double_t">Double_t</a> x = *pPos;
    <a href="../ListOfTypes.html#Double_t">Double_t</a> y = *(pPos + 1);

    if (pCur-&gt;pNextZ == 0) return 0;
    pNextVolume = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pNextZ;
    if (<a href="http://root.cern.ch/root/html/TMath.html#TMath:Sqrt">TMath::Sqrt</a>(x*x + y*y) &lt; pNextVolume-&gt;outerR) return 0;
  }

  pTraj-&gt;Update();

<b>  // We can update mcPart, but first we have to change doubles to floats</b>
  pMom = pTraj-&gt;GetNewMom();
  {
    <a href="../ListOfTypes.html#Float_t">Float_t</a> pos[3];
    <a href="../ListOfTypes.html#Float_t">Float_t</a> mom[3];

    for (<a href="../ListOfTypes.html#int">int</a> i = 0; i &lt; 3; i++) {
      pos[i] = *(pPos + i);
      mom[i] = *(pMom + i);
    }
    pTraj-&gt;GetMc()-&gt;SetParticleAtCal(&amp;mom[0], &amp;pos[0]);
  }

<b>  // Throw an interaction length or rad. length depending on particle type</b>
  totalPath = remPath = <a href="#CalRecon:RanExpDecay">RanExpDecay</a>(<a href=".././CalRecon.html#CalRecon:pRand">pRand</a>);

  while (true) {
    <a href="../ListOfTypes.html#Bool_t">Bool_t</a> helix;
    nVolume++;
    switch(status) {   // find new volume
    case <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ZMINUS">SmearTraj::INTERSECT_ZMINUS</a>:
    case <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ZPLUS">SmearTraj::INTERSECT_ZPLUS</a>:
      pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pNextZ;
      if (!pCur) return 0;
<b>      // In the special case in which we're coming from an endcap air</b>
<b>      // volume headed in a z-direction, there will typically be more </b>
<b>      // than one adjacent volume.  pNextZ pointer gives us innermost.</b>
<b>      // Check this against our current radius.  If necessary, follow</b>
<b>      // pNextR pointers until we find an acceptable volume</b>
      {
	<a href="../ListOfTypes.html#Double_t">Double_t</a> *newPos = pTraj-&gt;GetNewPos();
	<a href="../ListOfTypes.html#Double_t">Double_t</a> x = *newPos;
	<a href="../ListOfTypes.html#Double_t">Double_t</a> y = *(newPos + 1);
	<a href="../ListOfTypes.html#Double_t">Double_t</a> newR = <a href="http://root.cern.ch/root/html/TMath.html#TMath:Sqrt">TMath::Sqrt</a>(x*x + y*y);

	while (newR &gt; pCur-&gt;outerR) {
	  pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pNextR;
	  if (!pCur) return 0;
	}
      }
      break;
    case <a href=".././SmearTraj.html#SmearTraj:INTERSECT_CYLIN">SmearTraj::INTERSECT_CYLIN</a>:
<b>      // One extra thing to check here as well.  In case we go inwards, </b>
<b>      // there may be more than one component next to the original. </b>
<b>      // pPrevR points</b>
<b>      // to the one with smallest z.  If this isn't right (based on</b>
<b>      // new position), follow its pNextZ pointer.</b>
      
      {
	<a href="../ListOfTypes.html#Double_t">Double_t</a> *newPos = pTraj-&gt;GetNewPos();
	<a href="../ListOfTypes.html#Double_t">Double_t</a> newZ = <a href="http://root.cern.ch/root/html/TMath.html#TMath:Abs">TMath::Abs</a>(*(newPos + 2));
	pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pPrevR;
	if (!pCur) return 0;

	while (newZ &gt; pCur-&gt;outerZ) {
	  pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pNextZ;
	  if (!pCur) return 0;
	}
      }
      break;
    case <a href=".././SmearTraj.html#SmearTraj:INTERSECT_CYLOUT">SmearTraj::INTERSECT_CYLOUT</a>:
      pCur = (<a href=".././SmearVolume.html">SmearVolume</a> *) pCur-&gt;pNextR;
      break;
    default:
      return 0;
    }

    if (!pCur) return 0;  // Went outside detector

<b>    // Propagate to boundary of volume</b>
    helix = ((pCur-&gt;field != 0.0) &amp;&amp; (charge != 0));
    if (helix) { 
      status = pTraj-&gt;HelixToCyl(pCur, &amp;decrS);
    }
    else {  // straight line
      status = pTraj-&gt;LineToCyl(pCur, &amp;decrS);
    }
    if ((status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_NONE">SmearTraj::INTERSECT_NONE</a>) ||
	(status == <a href=".././SmearTraj.html#SmearTraj:INTERSECT_ERROR">SmearTraj::INTERSECT_ERROR</a>)  ) return 0;

    decrPath = decrS * (hadron ? pCur-&gt;iLenPerCm : pCur-&gt;radLenPerCm);

    if (decrPath &lt; remPath) { // keep going
      remPath -= decrPath;
      pTraj-&gt;Update();
    }
    else {  // We'll finish in this volume
      decrS = remPath / (hadron ? pCur-&gt;iLenPerCm : pCur-&gt;radLenPerCm);
      if (helix) {
	status = pTraj-&gt;HelixPath(pCur-&gt;field, decrS);
      }
      else status = pTraj-&gt;LinePath(decrS);

      nVolume++;
      pTraj-&gt;Update();
      return pCur;
    }
  }
}

</pre>

<!--SIGNATURE-->
<br>
<address>
<hr>
<center>
<a href="http://root.cern.ch/root/Welcome.html">ROOT page</a> - <a href="../ClassIndex.html">Class index</a> - <a href="#TopOfPage">Top of the page</a><br>
</center>
<hr>This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to <a href="mailto:rootdev@root.cern.ch">ROOT support</a>, or contact <a href="mailto:rootdev@root.cern.ch">the developers</a> with any questions or problems regarding ROOT.
</address>
</body>
</html>
