View Javadoc

1   package org.lcsim.geometry.segmentation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.jdom.DataConversionException;
7   import org.jdom.Element;
8   import org.lcsim.detector.identifier.ExpandedIdentifier;
9   import org.lcsim.detector.identifier.IExpandedIdentifier;
10  import org.lcsim.detector.identifier.IIdentifier;
11  import org.lcsim.detector.identifier.IIdentifierHelper;
12  import org.lcsim.detector.identifier.Identifier;
13  import org.lcsim.geometry.subdetector.AbstractPolyhedraCalorimeter;
14  import org.lcsim.geometry.util.BaseIDDecoder;
15  import org.lcsim.geometry.util.IDDescriptor;
16  import org.lcsim.geometry.util.IDEncoder;
17  
18  /**
19   * Extend XY Cartesian grid segmentation for neighboring across
20   * module boundaries.
21   * 
22   * @author cassell
23   */
24  public class RegularNgonCartesianGridXY extends CartesianGridXY
25  {	
26  	private double gridSizeX = 0;
27  	private double gridSizeY = 0;
28      private int nmodules = 12;
29  
30  	private int xIndex = -1;
31  	private int yIndex = -1;
32  	private int moduleIndex = -1;
33  
34      private int[] nvalidx;
35      private boolean[] borderCellIsDuplicate;
36      
37      private static final String fieldNames[] = {"x", "y"};
38  
39  	public RegularNgonCartesianGridXY(Element node) throws DataConversionException
40  	{
41  		super(node);
42  
43  		if (node.getAttribute("gridSizeX") != null)
44  		{
45  			gridSizeX = node.getAttribute("gridSizeX").getDoubleValue();
46  			cellSizes.add(0, gridSizeX);
47  		}
48  		else
49  		{
50  			throw new RuntimeException("Missing gridSizeX parameter.");
51  		}
52  
53  		if (node.getAttribute("gridSizeY") != null)
54  		{
55  			gridSizeY = node.getAttribute("gridSizeY").getDoubleValue();
56  			cellSizes.add(1, gridSizeY);
57  		}
58  		else
59  		{
60  			throw new RuntimeException("Missing gridSizeY parameter.");
61  		}
62  	}
63  	
64  	public String[] getSegmentationFieldNames() {
65  	    return fieldNames;
66  	}
67  	
68  	public long[] getNeighbourIDs(int layerRange, int xRange, int yRange)
69  	{
70  		if (this.getDecoder().getID() == 0)
71  			throw new RuntimeException("No current ID is set.");
72                  if(sensitiveSlices == null)initSensitiveSlices();
73          IDEncoder gnEncoder = new IDEncoder(descriptor);
74          BaseIDDecoder gnDecoder = new BaseIDDecoder(descriptor);
75          gnEncoder.setValues(values);
76          gnDecoder.setID(gnEncoder.getID());
77          IDEncoder dupEncoder = new IDEncoder(descriptor);
78          BaseIDDecoder dupDecoder = new BaseIDDecoder(descriptor);
79          dupEncoder.setValues(values);
80          dupDecoder.setID(dupEncoder.getID());
81  
82  	// Get number of layers.
83  	int nlayers = this.getNumberOfLayers();
84  
85  	// Set values for current id.
86  	int currLayer = values[layerIndex];
87  	int currX = gnDecoder.getValue(xIndex);
88  	int currY = gnDecoder.getValue(yIndex);
89          int currModule = gnDecoder.getValue(moduleIndex);
90  
91          // Initialize the border arrays the first time in
92          if (nvalidx == null)
93          {
94              initializeBorders();
95          }
96  	// Create return array.
97  	List<Long> neighbors = new ArrayList<Long>();
98  
99  	// Loop over layer range.
100 	for (int ilayer=-layerRange; ilayer<=layerRange; ilayer++)
101 	{
102             // Compute layer value.
103             int neighborLayer = currLayer + ilayer;
104 
105             if (neighborLayer >= 0 && neighborLayer < nlayers)
106             {
107                 gnEncoder.setValue(layerIndex, neighborLayer);
108                 // Loop over X range.
109                 for (int ix=-xRange; ix<=xRange; ix++)
110                 {
111                     // Need to check border
112                     int neighborX = currX + ix;
113                     int neighborModule = currModule;
114                     int dupX = neighborX;
115                     int dupModule = neighborModule;
116                     boolean dup = false;
117                     if(neighborX < -nvalidx[neighborLayer]+1)
118                     {
119                         if(neighborX == -nvalidx[neighborLayer])
120                         {
121                             if(borderCellIsDuplicate[neighborLayer])
122                             {
123                                 dup = true;
124                                 dupX = -neighborX -1;
125                                 dupModule = (nmodules + neighborModule -1)%nmodules;
126                             }
127                         }
128                         else
129                         {
130                             neighborModule = (nmodules + neighborModule -1)%nmodules;
131                             neighborX = 2*nvalidx[neighborLayer] + neighborX;
132                             if(borderCellIsDuplicate[neighborLayer])neighborX--;
133                         }
134                     }
135                     else if(neighborX > nvalidx[neighborLayer]-2)
136                     {
137                         if(neighborX == nvalidx[neighborLayer]-1)
138                         {
139                             if(borderCellIsDuplicate[neighborLayer])
140                             {
141                                 dup = true;
142                                 dupX = -neighborX -1;
143                                 dupModule = (neighborModule +1)%nmodules;
144                             }
145                         }
146                         else
147                         {
148                             neighborModule = (neighborModule +1)%nmodules;
149                             neighborX = -2*nvalidx[neighborLayer] + neighborX;
150                             if(borderCellIsDuplicate[neighborLayer])neighborX++;
151                         }
152                     }
153                     gnEncoder.setValue(xIndex, neighborX);
154                     gnEncoder.setValue(moduleIndex, neighborModule);
155                     // Loop over Y range.
156                     for (int iy=-yRange; iy<=yRange; iy++)
157                     {
158                         // Compute y value.
159 			int neighborY = currY + iy;
160 			// Set the neighbor fields.
161 			gnEncoder.setValue(yIndex, neighborY);
162 			// Add the neighbor id to the return array.
163                         if(sliceIndex >= 0)
164                         {
165                             // Loop over sensitive slices
166                             for(int is = 0;is < sensitiveSlices[neighborLayer].size();is++)
167                             {
168                                 // Set the slic field.
169                                 gnEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is))).intValue());
170 
171                                 if( this.getDecoder().getID()!= gnEncoder.getID())neighbors.add(gnEncoder.getID());
172                                 // If we have a duplicate cell, add it
173                                 if(dup)
174                                 {
175                                     dupEncoder.setValue(yIndex, neighborY);
176                                     dupEncoder.setValue(xIndex, dupX);
177                                     dupEncoder.setValue(layerIndex, neighborLayer);
178                                     dupEncoder.setValue(moduleIndex, dupModule);
179                                     dupEncoder.setValue(sliceIndex, ((Integer) (sensitiveSlices[neighborLayer].get(is))).intValue());
180                                     neighbors.add(dupEncoder.getID());
181                                 }
182                             }
183                         }
184                         else
185                         {
186                             if( this.getDecoder().getID()!= gnEncoder.getID())neighbors.add(gnEncoder.getID());
187                             // If we have a duplicate cell, add it
188                             if(dup)
189                             {
190                                 dupEncoder.setValue(yIndex, neighborY);
191                                 dupEncoder.setValue(xIndex, dupX);
192                                 dupEncoder.setValue(layerIndex, neighborLayer);
193                                 dupEncoder.setValue(moduleIndex, dupModule);
194                                 neighbors.add(dupEncoder.getID());
195                             }
196 
197                         }
198                     }
199 		}
200             }
201         }
202 
203 	long result[] = new long[neighbors.size()];
204 	int i = 0;
205 	for (Long id : neighbors)
206 	{
207             result[i] = id;
208             i++;
209 	}
210 	return result;
211     }
212     protected void initializeBorders()
213     {
214         nmodules = ((AbstractPolyhedraCalorimeter)getSubdetector()).getNumberOfSides();
215 		IIdentifierHelper helper = detector.getDetectorElement().getIdentifierHelper();
216         // Current packed id.
217         IIdentifier currId = new Identifier(this.getDecoder().getID());
218         // Create an ExpandedIdentifier for the current id.
219         IExpandedIdentifier thisId = helper.unpack(currId);
220         // nvalidx is the number of valid xbins in the elements half
221         // length per layer.
222         nvalidx = new int[this.getNumberOfLayers()];
223         // borderCellIsDuplicate - true if we treat the partial cell\
224         // on each side of the boundary as a single cell
225         borderCellIsDuplicate = new boolean[this.getNumberOfLayers()];
226         ExpandedIdentifier testId = new ExpandedIdentifier(thisId);
227         testId.setValue(moduleIndex,0);
228         long save = this.getDecoder().getID();
229         for(int layer=0;layer<this.getNumberOfLayers();layer++)
230         {
231 			testId.setValue(layerIndex, layer);
232             this.getDecoder().setID(helper.pack(testId).getValue());
233             this.computeGlobalPosition();
234             double yc = this.globalPosition[1];
235             double xhl = yc*Math.tan(Math.PI/nmodules);
236             nvalidx[layer] = (int)(xhl/gridSizeX) + 1;
237             double bcw = (nvalidx[layer]*gridSizeX - xhl)/gridSizeX;
238             borderCellIsDuplicate[layer] = false;
239             if(bcw < .5)borderCellIsDuplicate[layer] = true;
240         }
241 // Put back the cellID
242         this.getDecoder().setID(save);
243         this.computeGlobalPosition();
244     }
245 	public void setupGeomFields(IDDescriptor id)
246 	{
247         super.setupGeomFields(id);
248         xIndex = id.indexOf("x");
249 		yIndex = id.indexOf("y");
250 		layerIndex = id.indexOf("layer");
251 		moduleIndex = id.indexOf("module");
252 	}
253 		
254 }