View Javadoc

1   package org.lcsim.geometry.segmentation;
2   
3   import org.jdom.DataConversionException;
4   import org.jdom.Element;
5   import org.lcsim.geometry.util.IDDescriptor;
6   import org.lcsim.geometry.util.IDEncoder;
7   
8   /**
9    * This segmentation represents a projective cylinder.  It is most 
10   * appropriately used in a cylindrical calorimeter barrel.
11   * 
12   * @author Tony Johnson <tonyj@slac.stanford.edu>
13   */
14  public class ProjectiveCylinder extends BarrelCylinderSegmentationBase
15  {
16      private int thetaBins;
17      private int phiBins;
18  
19      private int thetaIndex;
20      private int phiIndex;
21      private int barrelIndex = -1;
22      private int systemIndex = -1;
23      
24      private static final String fieldNames[] = {"phi", "theta"};
25  
26      ProjectiveCylinder(Element node) throws DataConversionException
27      {
28          super(node);
29          thetaBins = node.getAttribute("thetaBins").getIntValue();
30          phiBins = node.getAttribute("phiBins").getIntValue();
31      }
32      
33      public String[] getSegmentationFieldNames() {
34          return fieldNames;
35      }
36      
37      public double getCellSizeU()
38      {
39          return getTheta();
40      }
41      
42      public double getCellSizeV()
43      {
44          return getPhi();
45      }
46  
47      /**
48       * FIXME Cache this value in ctor.
49       */
50      public double getPhi()
51      {
52          return Math.PI * 2 * (getValue(phiIndex) + 0.5) / phiBins;
53      }
54  
55      /**
56       * FIXME Cache this value in ctor.
57       */
58      public double getTheta()
59      {
60          return Math.PI * (getValue(thetaIndex) + 0.5) / thetaBins;
61      }
62  
63      public double getX()
64      {
65          return getDistanceToSensitive(getLayer()) * Math.cos(getPhi());
66      }
67  
68      public double getY()
69      {
70          return getDistanceToSensitive(getLayer()) * Math.sin(getPhi());
71      }
72  
73      public double getZ()
74      {
75          double cosTheta = Math.cos(getTheta());
76          return getDistanceToSensitive(getLayer()) * cosTheta / Math.sqrt(1 - cosTheta * cosTheta);
77      }
78  
79      public void setIDDescription(IDDescriptor id)
80      {
81          super.setIDDescription(id);
82  
83          phiIndex = id.indexOf("phi");
84          thetaIndex = id.indexOf("theta");
85          barrelIndex = id.indexOf("barrel");
86          systemIndex = id.indexOf("system");
87      }
88  
89      public boolean supportsNeighbours()
90      {
91          return true;
92      }
93  
94      public long[] getNeighbourIDs(int deltaLayer, int deltaTheta, int deltaPhi)
95      {
96          IDEncoder encoder = new IDEncoder(descriptor);
97          encoder.setValues(values);
98  
99          int nMax = (2*deltaLayer + 1)*(2*deltaTheta + 1)*(2*deltaPhi + 1) - 1;
100         int size = 0;
101         long[] result = new long[nMax];
102         for (int i = -deltaLayer; i <= deltaLayer; i++)
103         {
104             int l = values[layerIndex] + i;
105 
106             if (l<0 || l>= getNumberOfLayers() ) continue;
107             encoder.setValue(layerIndex,l);
108 
109             for (int j = -deltaTheta; j <= deltaTheta; j++)
110             {
111                 int t = values[thetaIndex] + j;
112 
113                 if (t<0 || t>=thetaBins) continue;
114                 encoder.setValue(thetaIndex,t);
115 
116                 for (int k = -deltaPhi; k <= deltaPhi; k++)
117                 {
118                     if (i==0 && j==0 && k==0) continue;
119 
120                     int p = values[phiIndex] + k;
121                     if(p<0) p+=phiBins;
122                     if(p>=phiBins) p-=phiBins;
123 
124                     result[size++] = encoder.setValue(phiIndex, p);
125                 }
126             }
127         }
128         if (size < result.length)
129         {
130             long[] temp = new long[size];
131             System.arraycopy(result, 0, temp, 0, size);
132             result = temp;
133         }
134         return result;
135     }
136 
137     public int getThetaBins()
138     {
139         return thetaBins;
140     }
141 
142     public int getPhiBins()
143     {
144         return phiBins;
145     }
146 
147     /**
148      * Return the cell which contains a given point (x,y,z), or zero.
149      *
150      * @param x Cartesian X coordinate.
151      * @param y Cartesian Y coordinate.
152      * @param z Cartesian Z coordinate.     
153      * 
154      * @return ID of cell containing the point (maybe either in absorber
155      *         or live material)
156      */
157     public long findCellContainingXYZ(double x, double y, double z)
158     {
159 
160         // validate point
161         if(z<getZMin()) return 0;
162         if(z>getZMax()) return 0;
163         double rho = Math.sqrt(x*x+y*y);
164         if(rho<getRMin()) return 0;
165         if(rho>getRMax()) return 0;
166 
167         // ok, point is valid, so a valid ID should be returned
168         int ilay = getLayerBin(rho);
169 
170         double phi = Math.atan2(y, x);
171         if (phi < 0)
172             phi += 2 * Math.PI;
173         int iphi = (int) (phi * phiBins / (2 * Math.PI));
174 
175         double theta = Math.atan2(rho, z);
176         int itheta = (int) (theta * thetaBins / Math.PI);
177 
178         IDEncoder enc = new IDEncoder(descriptor);
179         enc.setValue(layerIndex, ilay);
180         enc.setValue(thetaIndex, itheta);
181         enc.setValue(phiIndex, iphi);
182         enc.setValue(barrelIndex, 0);
183         enc.setValue(systemIndex, detector.getSystemID());
184         long resultID = enc.getID();
185 
186         return resultID;
187     }
188 }