1 package org.lcsim.recon.tracking.vsegment.geom; 2 3 import java.util.*; 4 5 import org.lcsim.event.SimTrackerHit; 6 import org.lcsim.geometry.Detector; 7 8 /** 9 * Base class for implementing {@link Segmenter}s that describe virtual segmentation 10 * of a certain part of the detector. 11 * <p> 12 * Within that part, each <tt>Sensor</tt> is identified by a unique integer <tt>postfix</tt>. 13 * Each <tt>RegionSegmenter</tt> can be assigned an integer <tt>prefix</tt>. After that, 14 * <tt>SensorID</tt> values returned by <tt>getSensorID(SimTrackerHit)</tt> method and assigned to 15 * <tt>Sensor</tt> objects created by this segmenter will be composed of bits 16 * containing the <tt>prefix</tt> and bits containing the <tt>postfix</tt>. 17 * <p> 18 * Objects of this class are intended to be used either as top level segmenters 19 * describing segmentation of the whole detector and provided directly to 20 * {@link SegmentationManager} in its constructor, or as bottom level segmenters 21 * in a tree of <tt>AbstractSegmenters</tt>. In the latter case, they should be added as 22 * daughters to <tt>ForwardingSegmenters</tt>, and their prefixes will be set automatically. 23 * See {@link AbstractSegmenter} for details on how to chain <tt>Segmenters</tt>. 24 * <p> 25 * Subclasses should implement {@link #makePostfix(SimTrackerHit)}, {@link #makeSensor(int)}, 26 * {@link #getMaxPostfix()}, and {@link #isPostfixValid(int)} methods. In addition, 27 * {@link #detectorChanged(Detector)} method can be overridden if any detector 28 * dependent initialization is required. 29 * 30 * @author D. Onoprienko 31 * @version $Id: RegionSegmenter.java,v 1.1 2008/12/06 21:53:43 onoprien Exp $ 32 */ 33 abstract public class RegionSegmenter extends AbstractSegmenter { 34 35 // -- Constructors : ---------------------------------------------------------- 36 37 /** Default constructor. */ 38 protected RegionSegmenter() { 39 } 40 41 // -- To be implemented by subclusses : --------------------------------------- 42 43 /** 44 * Subclasses should implement this method to return <tt>postfix</tt> corresponding 45 * to the position of the given simulated hit. 46 * The <tt>postfix</tt> must be non-negative integer, unique within the part of 47 * the detector handled by this <tt>Segmenter</tt> object. If the hit is outside 48 * of any sensor, "-1" should be returned. 49 */ 50 abstract protected int makePostfix(SimTrackerHit hit); 51 52 /** 53 * Subclasses should implement this method to create a new {@link Sensor} object given 54 * the <tt>postfix</tt>. If the postfix is invalid, <tt>null</tt> should be returned. 55 */ 56 abstract protected Sensor makeSensor(int postfix); 57 58 /** 59 * Subclasses should implement this method to return maximum postfix value that can be 60 * returned by {@link #makePostfix(SimTrackerHit)} method of this <tt>Segmenter</tt> object. 61 */ 62 abstract protected int getMaxPostfix(); 63 64 /** 65 * Subclasses should override this method to return <tt>true</tt> if the given 66 * <tt>postfix</tt> corresponds to a valid <tt>Sensor</tt> object that can be created 67 * by this <tt>RegionSegmenter</tt>. Default implementation is provided, returning 68 * <tt>true</tt> if the value of <tt>postfix</tt> is between zero and the value 69 * returned by {@link #getMaxPostfix()}. 70 */ 71 protected boolean isPostfixValid(int postfix) { 72 return postfix >= 0 && postfix <= getMaxPostfix(); 73 } 74 75 // -- Implementing Segmenter : ------------------------------------------------ 76 77 /** 78 * Returns a collection of <tt>Sensors</tt> corresponding to all virtual segments 79 * in the part of the detector handled by this <tt>Segmenter</tt>. 80 */ 81 public List<Integer> getSensorIDs() { 82 int nSensors = getMaxPostfix() + 1; 83 ArrayList<Integer> sensorIDs = new ArrayList<Integer>(nSensors); 84 for (int postfix=0; postfix < nSensors; postfix++) { 85 if (isPostfixValid(postfix)) sensorIDs.add(postfixToID(postfix)); 86 } 87 //System.out.println("Segmenter "+this+" returning "+sensorIDs.size()+" IDs"); 88 return sensorIDs; 89 } 90 91 /** 92 * Returns integer <tt>SensorID</tt> uniquely identifying a {@link Sensor} object 93 * within the whole detector, given the simulated hit. 94 */ 95 public int getSensorID(SimTrackerHit hit) { 96 int postfix = makePostfix(hit); 97 // if (postfix == -1) { 98 // System.out.println(" "); 99 // System.out.println("From RegionSegmenter.getSensorID(hit) :"); 100 // System.out.println("Segmenter " + this + " failed to produce Sensor"); 101 // System.out.println("for hit in " + hit.getSubdetector().getName() + " layer " + hit.getLayer()); 102 // System.out.println(" "); 103 // } 104 return (postfix == -1) ? -1 : postfixToID(postfix); 105 } 106 107 /** 108 * Creates a new {@link Sensor} object given full <tt>SensorID</tt>. 109 * For the sake of speed, no checking is done to verify that the supplied 110 * <tt>SensorID</tt> belongs to the part of the detector that should be handled 111 * by this <tt>OldSegmenter</tt> - be careful. 112 */ 113 public Sensor getSensor(int sensorID) { 114 return makeSensor(idToPostfix(sensorID)); 115 } 116 117 /** 118 * Creates a new {@link Sensor} object given simulated hit. 119 */ 120 public Sensor getSensor(SimTrackerHit hit) { 121 int postfix = makePostfix(hit); 122 return (postfix == -1) ? null : makeSensor(postfix); 123 } 124 125 /** 126 * Called by the framework whenever detector geometry changes. 127 * Subclasses can override this method if they need to perform any 128 * detector-dependent initialization. 129 */ 130 public void detectorChanged(Detector detector) { 131 // System.out.println(" "); 132 // System.out.println("Updated " + this + " with " + detector.getName()); 133 // System.out.println("Created " + (getMaxPostfix()+1) + " sensors"); 134 } 135 136 /** 137 * Returns a list of <tt>Sensors</tt> that might contain hits that should be combined 138 * with hits in the <tt>Sensor</tt> whose <tt>sensorID</tt> is supplied as an argument 139 * to form stereo pairs. 140 * Default implementation returns an empty list. Subclasses may override. 141 */ 142 public List<Integer> getStereoPartners(int sensorID) { 143 return Collections.emptyList(); 144 } 145 146 // -- Handling prefixes and postfixes : --------------------------------------- 147 148 /** 149 * Set <tt>pretfix</tt> value and <tt>postfix</tt> length for this <tt>Segmenter</tt>. 150 */ 151 public void setPrefix(int prefix, int postfixLength) { 152 // System.out.println("Setting prefix for "+this+" prefix "+prefix+" length "+postfixLength); 153 super.setPrefix(prefix, postfixLength); 154 if (getIdSize(prefix) + postfixLength > 32) { 155 throw new IllegalArgumentException("Combined prefix and postfix length cannot be more than 32"); 156 } else if (postfixLength < getNativePostfixLength()) { 157 throw new IllegalArgumentException("Attempt to set insufficient postfix length"); 158 } 159 } 160 161 /** 162 * Returns minimum number of bits required to hold any postfix that can be returned by 163 * {@link #makePostfix(SimTrackerHit)} method of this <tt>Segmenter</tt>. 164 */ 165 public int getNativePostfixLength() { 166 return getIdSize(getMaxPostfix()); 167 } 168 169 }