Skip to content

Commit 2239be3

Browse files
committed
generalize occupancyplots to include slim edge sensors; code migrated, untested thus far
1 parent 1b1bc23 commit 2239be3

1 file changed

Lines changed: 131 additions & 31 deletions

File tree

tracking/src/main/java/org/hps/svt/OccupancyPlots.java

Lines changed: 131 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
import org.lcsim.detector.ITransform3D;
1616
import org.lcsim.detector.tracker.silicon.ChargeCarrier;
1717
import org.lcsim.detector.tracker.silicon.HpsSiSensor;
18-
import org.lcsim.detector.tracker.silicon.SiStrips;
18+
import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
19+
import org.lcsim.detector.tracker.silicon.SiStriplets;
1920
import org.lcsim.event.EventHeader;
2021
import org.lcsim.event.GenericObject;
2122
import org.lcsim.event.RawTrackerHit;
@@ -155,10 +156,15 @@ public static Map<Integer, Hep3Vector> createStripPositionMap(HpsSiSensor sensor
155156
Map<Integer, Hep3Vector> positionMap = new HashMap<Integer, Hep3Vector>();
156157
for (ChargeCarrier carrier : ChargeCarrier.values()) {
157158
if (sensor.hasElectrodesOnSide(carrier)) {
158-
SiStrips strips = (SiStrips) sensor.getReadoutElectrodes(carrier);
159+
// Declared as the interface rather than SiStrips: L0 sensors
160+
// (HpsThinSiSensor) carry SiStriplets, which extend SiPixels and
161+
// are not SiStrips. getCellPosition() is on the interface and
162+
// SiStriplets overrides it to return the striplet centre, so the
163+
// polymorphic call is correct for both.
164+
SiSensorElectrodes strips = sensor.getReadoutElectrodes(carrier);
159165
ITransform3D parentToLocal = sensor.getReadoutElectrodes(carrier).getParentToLocal();
160166
ITransform3D localToGlobal = sensor.getReadoutElectrodes(carrier).getLocalToGlobal();
161-
for (int physicalChannel = 0; physicalChannel < 640; physicalChannel++) {
167+
for (int physicalChannel = 0; physicalChannel < sensor.getNumberOfChannels(); physicalChannel++) {
162168
Hep3Vector localStripPosition = strips.getCellPosition(physicalChannel);
163169
Hep3Vector stripPosition = parentToLocal.transformed(localStripPosition);
164170
Hep3Vector globalStripPosition = localToGlobal.transformed(stripPosition);
@@ -168,7 +174,66 @@ public static Map<Integer, Hep3Vector> createStripPositionMap(HpsSiSensor sensor
168174
}
169175
return positionMap;
170176
}
171-
177+
178+
/**
179+
* Get the number of readout columns of a sensor. Strip sensors (L1-L6, and
180+
* all layers of the pre-2019 geometry) have a single column. L0 striplet
181+
* sensors split their strips into two columns along the strip direction.
182+
*
183+
* @param sensor : HpsSiSensor
184+
* @return The number of columns, always >= 1
185+
*/
186+
private static int getNumberOfColumns(HpsSiSensor sensor) {
187+
SiSensorElectrodes electrodes = sensor.getReadoutElectrodes(ChargeCarrier.HOLE);
188+
// Axis 1 is the column axis for both SiStrips (where it is 1) and
189+
// SiStriplets (where it is 2), but only when the electrodes are 2D.
190+
return electrodes.getNAxes() > 1 ? electrodes.getNCells(1) : 1;
191+
}
192+
193+
/**
194+
* Get the readout column a physical channel belongs to.
195+
*
196+
* Note that SiSensorElectrodes.getColumnNumber(int) is NOT consistent across
197+
* implementations - SiStriplets returns the column, but SiStrips subclasses
198+
* return the strip number itself - so it can only be called on striplets.
199+
*
200+
* @param sensor : HpsSiSensor
201+
* @param physicalChannel : physical channel number
202+
* @return The column number, 0 for strip sensors
203+
*/
204+
private static int getColumnNumber(HpsSiSensor sensor, int physicalChannel) {
205+
SiSensorElectrodes electrodes = sensor.getReadoutElectrodes(ChargeCarrier.HOLE);
206+
if (electrodes instanceof SiStriplets) {
207+
return ((SiStriplets) electrodes).getColumnNumber(physicalChannel);
208+
}
209+
return 0;
210+
}
211+
212+
/**
213+
* Get the plot name suffix identifying a column.
214+
*
215+
* Empty for single-column (strip) sensors, so that both the map keys and the
216+
* histogram names are unchanged from the pre-L0 behaviour.
217+
*
218+
* @param sensor : HpsSiSensor
219+
* @param column : column number
220+
* @return The suffix
221+
*/
222+
private static String getColumnSuffix(HpsSiSensor sensor, int column) {
223+
return getNumberOfColumns(sensor) == 1 ? "" : " - Column " + column;
224+
}
225+
226+
/**
227+
* Get the key used to store the per-column position plots of a sensor.
228+
*
229+
* @param sensor : HpsSiSensor
230+
* @param column : column number
231+
* @return The map key
232+
*/
233+
private static String getPositionPlotKey(HpsSiSensor sensor, int column) {
234+
return sensor.getName() + getColumnSuffix(sensor, column);
235+
}
236+
172237
//Grab the channel associated with the cluster based on position.
173238
private int getClusterChan(SiTrackerHitStrip1D h, HpsSiSensor sensor){
174239
List<RawTrackerHit> rawhits = h.getRawHits();
@@ -178,10 +243,12 @@ private int getClusterChan(SiTrackerHitStrip1D h, HpsSiSensor sensor){
178243
Hep3Vector pos_global = global.getPositionAsVector();
179244
double clusterHitPos = pos_global.y();
180245
RawTrackerHit hit = rawhits.get(0);
181-
int chan = hit.getIdentifierFieldValue("strip");
182-
double diffmin = Math.abs(getStripPosition(sensor,chan).y() - clusterHitPos);
246+
double diffmin = Double.MAX_VALUE;
183247
for(RawTrackerHit rawhit : rawhits){
184248
int chanhit = rawhit.getIdentifierFieldValue("strip");
249+
// Unbonded channels past the last readout channel have no entry in
250+
// the strip position map.
251+
if (!sensor.isValidChannel(chanhit)) continue;
185252
double diff = Math.abs(getStripPosition(sensor,chanhit).y() - clusterHitPos);
186253
if(diff < diffmin){
187254
diffmin = diff;
@@ -209,8 +276,10 @@ private void resetPlots() {
209276
clusterOccupancyPlots.get(sensor.getName()).reset();
210277

211278
if (enablePositionPlots) {
212-
positionPlots.get(sensor.getName()).reset();
213-
clusterPositionPlots.get(sensor.getName()).reset();
279+
for (int column = 0; column < getNumberOfColumns(sensor); column++) {
280+
positionPlots.get(getPositionPlotKey(sensor, column)).reset();
281+
clusterPositionPlots.get(getPositionPlotKey(sensor, column)).reset();
282+
}
214283
//clusterPositionPlotCounts.get(sensor.getName()).reset();
215284
}
216285

@@ -219,8 +288,8 @@ private void resetPlots() {
219288
}
220289

221290
// Reset the hit counters.
222-
occupancyMap.put(sensor.getName(), new int[640]);
223-
clusterOccupancyMap.put(sensor.getName(), new int[640]);
291+
occupancyMap.put(sensor.getName(), new int[sensor.getNumberOfChannels()]);
292+
clusterOccupancyMap.put(sensor.getName(), new int[sensor.getNumberOfChannels()]);
224293
}
225294
}
226295

@@ -252,11 +321,18 @@ protected void detectorChanged(Detector detector) {
252321
occupancyPlots.put(sensor.getName(),histogramFactory.createHistogram1D(sensor.getName() + " - Occupancy", nChan, 0, nChan));
253322
clusterOccupancyPlots.put(sensor.getName(),histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Occupancy", nChan, 0, nChan));
254323
if (enablePositionPlots){
255-
positionPlots.put(sensor.getName(),histogramFactory.createHistogram1D(sensor.getName() + " - Occupancy vs Position", 1000, -60, 60));
256-
clusterPositionPlots.put(sensor.getName(),histogramFactory.createHistogram1D(sensor.getName() + " - Cluster occupancy vs Position", 1000, -60, 60));
324+
// Strip sensors have a single column and keep the original plot
325+
// names. L0 striplet sensors get one plot per column, so that the
326+
// channel to position mapping stays one to one within each plot.
327+
for (int column = 0; column < getNumberOfColumns(sensor); column++) {
328+
String key = getPositionPlotKey(sensor, column);
329+
String suffix = getColumnSuffix(sensor, column);
330+
positionPlots.put(key,histogramFactory.createHistogram1D(sensor.getName() + " - Occupancy vs Position" + suffix, 1000, -60, 60));
331+
clusterPositionPlots.put(key,histogramFactory.createHistogram1D(sensor.getName() + " - Cluster occupancy vs Position" + suffix, 1000, -60, 60));
332+
}
257333
}
258-
occupancyMap.put(sensor.getName(), new int[640]);
259-
clusterOccupancyMap.put(sensor.getName(), new int[640]);
334+
occupancyMap.put(sensor.getName(), new int[nChan]);
335+
clusterOccupancyMap.put(sensor.getName(), new int[nChan]);
260336
if (enableMaxSamplePlots)
261337
maxSamplePositionPlots.put(sensor.getName(),histogramFactory.createHistogram1D(sensor.getName() + " - Max Sample Number", 6, -0.5, 5.5));
262338
}
@@ -342,8 +418,15 @@ public void process(EventHeader event) {
342418
}
343419

344420
if (maxSamplePosition == -1 || maxSamplePosition == maxSamplePositionFound) {
345-
occupancyMap.get(((HpsSiSensor) rawHit.getDetectorElement()).getName())[rawHit
346-
.getIdentifierFieldValue("strip")]++;
421+
HpsSiSensor sensor = (HpsSiSensor) rawHit.getDetectorElement();
422+
int strip = rawHit.getIdentifierFieldValue("strip");
423+
// Raw hits can carry the unbonded channel one past the last
424+
// readout channel (639 on a 639 channel strip sensor), which
425+
// StripMaker also drops. It has no strip position and no
426+
// histogram bin, so skip it rather than index past the counters.
427+
if (sensor.isValidChannel(strip)) {
428+
occupancyMap.get(sensor.getName())[strip]++;
429+
}
347430
}
348431

349432
if (enableMaxSamplePlots) {
@@ -356,14 +439,18 @@ public void process(EventHeader event) {
356439
if (event.hasCollection(SiTrackerHitStrip1D.class, stripClusterCollectionName)) {
357440
List<SiTrackerHitStrip1D> stripHits1D = event.get(SiTrackerHitStrip1D.class, stripClusterCollectionName);
358441
for (SiTrackerHitStrip1D h : stripHits1D) {
359-
int chan = getClusterChan(h,((HpsSiSensor) h.getRawHits().get(0).getDetectorElement()));
360-
442+
HpsSiSensor sensor = (HpsSiSensor) h.getRawHits().get(0).getDetectorElement();
443+
int chan = getClusterChan(h, sensor);
444+
if (!sensor.isValidChannel(chan)) {
445+
continue;
446+
}
447+
361448
if (enableClusterTimeCuts) {
362449
if (h.getTime() < clusterTimeCutMax && h.getTime() > clusterTimeCutMin) {
363-
clusterOccupancyMap.get(((HpsSiSensor) h.getRawHits().get(0).getDetectorElement()).getName())[chan]++;
450+
clusterOccupancyMap.get(sensor.getName())[chan]++;
364451
}
365452
} else {
366-
clusterOccupancyMap.get(((HpsSiSensor) h.getRawHits().get(0).getDetectorElement()).getName())[chan]++;
453+
clusterOccupancyMap.get(sensor.getName())[chan]++;
367454
}
368455
}
369456
}
@@ -376,7 +463,9 @@ public void process(EventHeader event) {
376463
occupancyPlots.get(sensor.getName()).reset();
377464
clusterOccupancyPlots.get(sensor.getName()).reset();
378465
if (enablePositionPlots) {
379-
positionPlots.get(sensor.getName()).reset();
466+
for (int column = 0; column < getNumberOfColumns(sensor); column++) {
467+
positionPlots.get(getPositionPlotKey(sensor, column)).reset();
468+
}
380469
}
381470
for (int channel = 0; channel < strips.length; channel++) {
382471
double stripOccupancy = (double) strips[channel] / (double) eventCount;
@@ -385,7 +474,7 @@ public void process(EventHeader event) {
385474

386475
if (enablePositionPlots) {
387476
double stripPosition = this.getStripPosition(sensor, channel).y();
388-
positionPlots.get(sensor.getName()).fill(stripPosition, stripOccupancy);
477+
positionPlots.get(getPositionPlotKey(sensor, getColumnNumber(sensor, channel))).fill(stripPosition, stripOccupancy);
389478
}
390479
}
391480
for (int channel = 0; channel < clusterStrips.length; channel++) {
@@ -395,7 +484,7 @@ public void process(EventHeader event) {
395484

396485
if (enablePositionPlots) {
397486
double clusterPosition = this.getStripPosition(sensor, channel).y();
398-
clusterPositionPlots.get(sensor.getName()).fill(clusterPosition, clusterOccupancy);
487+
clusterPositionPlots.get(getPositionPlotKey(sensor, getColumnNumber(sensor, channel))).fill(clusterPosition, clusterOccupancy);
399488
}
400489
}
401490
}
@@ -409,19 +498,30 @@ public void endOfData() {
409498
System.out.println("%======================== Active Edge Sensor Occupancies =======================%");
410499
System.out.println("%===============================================================================%");
411500
System.out.println("% Total Events: " + eventCount);
412-
// Calculate the occupancies at the sensor edge
413-
int[] topActiveEdgeStripOccupancy = new int[6];
414-
int[] bottomActiveEdgeStripOccupancy = new int[6];
501+
// Calculate the occupancies at the sensor edge. The number of layers is
502+
// taken from the geometry rather than assumed to be 6, since the 2019+
503+
// geometry adds L0 for a total of 7.
504+
int nLayers = 0;
505+
for (HpsSiSensor sensor : sensors) {
506+
nLayers = Math.max(nLayers, getLayerNumber(sensor));
507+
}
508+
int[] topActiveEdgeStripOccupancy = new int[nLayers];
509+
int[] bottomActiveEdgeStripOccupancy = new int[nLayers];
415510
for (HpsSiSensor sensor : sensors) {
511+
// The active edge is the last channel on the positron side and the
512+
// second channel on the electron side. Both are sensor-size
513+
// dependent: 638 (of 639) and 1 for strip sensors, 511 (of 512) and 1
514+
// for L0 striplet sensors.
515+
int edgeChannel = sensor.getNumberOfChannels() - 1;
416516
if (sensor.isTopLayer() && sensor.isAxial()) {
417517
if (sensor.getSide().equals(HpsSiSensor.ELECTRON_SIDE)) {
418518
System.out.println("% Top Layer " + getLayerNumber(sensor) + " Hit Counts: "
419519
+ occupancyMap.get(sensor.getName())[1]);
420520
topActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[1];
421521
} else {
422522
System.out.println("% Top Layer " + getLayerNumber(sensor) + " Hit Counts: "
423-
+ occupancyMap.get(sensor.getName())[638]);
424-
topActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[638];
523+
+ occupancyMap.get(sensor.getName())[edgeChannel]);
524+
topActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[edgeChannel];
425525
}
426526
} else if (sensor.isBottomLayer() && sensor.isAxial()) {
427527
if (sensor.getSide().equals(HpsSiSensor.ELECTRON_SIDE)) {
@@ -430,13 +530,13 @@ public void endOfData() {
430530
bottomActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[1];
431531
} else {
432532
System.out.println("% Bottom Layer " + getLayerNumber(sensor) + " Hit Counts: "
433-
+ occupancyMap.get(sensor.getName())[638]);
434-
bottomActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[638];
533+
+ occupancyMap.get(sensor.getName())[edgeChannel]);
534+
bottomActiveEdgeStripOccupancy[getLayerNumber(sensor) - 1] += occupancyMap.get(sensor.getName())[edgeChannel];
435535
}
436536
}
437537
}
438538

439-
for (int layerN = 0; layerN < 6; layerN++) {
539+
for (int layerN = 0; layerN < nLayers; layerN++) {
440540
double topStripOccupancy = (double) topActiveEdgeStripOccupancy[layerN] / (double) eventCount;
441541
topStripOccupancy /= this.timeWindowWeight;
442542
System.out.println("% Top Layer " + (layerN + 1) + ": Occupancy in " + (24 / this.timeWindowWeight)

0 commit comments

Comments
 (0)