View Javadoc

1   package org.lcsim.mc.fast.cluster.ronan;
2   
3   import org.lcsim.mc.fast.MCFast;
4   import hep.physics.particle.Particle;
5   import java.util.Collections;
6   import java.util.List;
7   import java.util.Random;
8   import org.lcsim.event.Cluster;
9   
10  public abstract class ReconCluster implements Cluster {
11      protected ClusterResolutionTables parm;
12      protected Particle mcp;
13      protected double a = 0;
14      protected double b = 0;
15      protected double c = 0;
16      protected double d = 0;
17      protected double energy;
18      protected double energyError;
19      protected double neg_energy;
20      protected double sigma;
21      protected double phi;
22      protected double radius;
23      protected double theta;
24      protected double transDist;
25  
26      ReconCluster(ClusterResolutionTables parm, Random rand, Particle mcp, boolean hist) {
27          this.parm = parm;
28          this.mcp = mcp;
29      }
30  
31      /** Best estimate for total energy of cluster */
32      public double getEnergy() {
33          return energy;
34      }
35  
36      public double getEnergyError() {
37          return energyError;
38      }
39  
40      public void setEnergyError(double energyError) {
41          this.energyError = energyError;
42      }
43  
44      public double getNegEnergy() {
45          return neg_energy;
46      }
47  
48      public double getSigma() {
49          return sigma;
50      }
51  
52      public void adjustEnergy(double neg_energy_total, double pos_energy_weight_total) {
53          MCFast.log.info(" min(sigma,energy)=" + Math.min(sigma, energy) + " ratio= " + (Math.min(sigma, energy) / pos_energy_weight_total) + " before adjust energy= " + energy);
54          energy += neg_energy_total * Math.min(sigma, energy) / pos_energy_weight_total;
55  
56          if (energy <= mcp.getMass())
57              energy = mcp.getMass() + Double.MIN_VALUE;
58  
59          MCFast.log.info(" neg_energy_total= " + neg_energy_total + " after adjust energy= " + energy);
60      }
61  
62      protected void smear(Random rand, boolean hist) {
63          // Get true energy from MCParticle
64          double E = mcp.getEnergy();
65  
66          // Smear reconstructed energy
67  
68          smearEnergy(rand, E, hist);
69  
70          // Smear reconstructed position
71          smearPosition(rand, E, hist);
72      }
73  
74      protected void smearEnergy(Random rand, double E, boolean hist) {
75          sigma = Math.sqrt(Math.pow(a, 2.) * E + Math.pow(b * E, 2.));
76  
77          energy = E + (sigma * rand.nextGaussian());
78          if (energy <= mcp.getMass()) {
79              neg_energy = energy - mcp.getMass();
80              energy = mcp.getMass() + Double.MIN_VALUE;
81          } else {
82              neg_energy = 0.;
83          }
84      }
85  
86      protected void smearPosition(Random rand) {
87          // Get true direction from MCParticle
88          double Px = mcp.getPX();
89          double Py = mcp.getPY();
90          double Pz = mcp.getPZ();
91  
92          double P = Math.sqrt((Px * Px) + (Py * Py) + (Pz * Pz));
93          double Phi = Math.atan2(Py, Px);
94          if (Phi < 0) {
95              Phi += (2 * Math.PI);
96          }
97  
98          double Theta = Math.acos(Pz / P);
99  
100         // Simulate position smearing on a sphere of radius 2 meters
101         radius = 2000.0;
102 
103         double x = (radius * Px) / P;
104         double y = (radius * Py) / P;
105         double z = (radius * Pz) / P;
106 
107         // these vectors vt and vs (orthonorm.) span a plane perpendicular to the momentum vector,
108         // so smearing with a transdist will involve a lin. comb. of these
109         double[] vt = { -Math.cos(Theta) * Math.cos(Phi), -Math.cos(Theta) * Math.sin(Phi), Math.sin(Theta) };
110         double[] vs = { Math.sin(Phi), -Math.cos(Phi), 0 };
111 
112         // restricted to [0,PI] since transdist can be negative
113         double alpha = rand.nextDouble() * Math.PI;
114         x = x + transDist * (Math.cos(alpha) * vt[0] + Math.sin(alpha) * vs[0]);
115         y = y + transDist * (Math.cos(alpha) * vt[1] + Math.sin(alpha) * vs[1]);
116         z = z + transDist * (Math.cos(alpha) * vt[2] + Math.sin(alpha) * vs[2]);
117 
118         phi = Math.atan2(y, x);
119         if (phi < 0) {
120             phi += (2 * Math.PI);
121         }
122         theta = Math.acos(z / radius);
123     }
124 
125     public Particle getMCParticle() {
126         return mcp;
127     }
128 
129     abstract void smearPosition(Random rand, double E, boolean hist);
130 
131     public double[] getHitContributions() {
132         return null;
133     }
134 
135     public List getClusters() {
136         return Collections.EMPTY_LIST;
137     }
138 
139     public double[] getSubdetectorEnergies() {
140         return null;
141     }
142 
143     public double[] getPositionError() {
144         return null; // fixme:
145     }
146 
147     public int getType() {
148         return 0; // Fixme:
149     }
150 
151     public double getITheta() {
152         return 0; // Fixme:
153     }
154 
155     public double getIPhi() {
156         return 0; // Fixme:
157     }
158 
159     public double[] getDirectionError() {
160         return null; // Fixme:
161     }
162 
163     public List getCalorimeterHits() {
164         return Collections.EMPTY_LIST;
165     }
166 
167     public double[] getShape() {
168         return null;
169     }
170 
171     public double[] getPosition() {
172         double x = radius * Math.sin(theta) * Math.cos(phi);
173         double y = radius * Math.sin(theta) * Math.sin(phi);
174         double z = radius * Math.cos(theta);
175         return new double[] { x, y, z };
176     }
177 
178     public double[] getParticleType() {
179         return null; // Fixme:
180     }
181 
182     public int getParticleId() {
183         return 0;
184     }
185 
186     public int getSize() {
187         return 0;
188     }
189 }