Author: [log in to unmask]
Date: Mon Feb 23 17:38:59 2015
New Revision: 3553
Log:
Add HPS ECAL geometry API including crystal neighboring. HPSJAVA-417, LCSIM-243
Added:
projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java
projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java
projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java
Modified:
projects/lcsim/trunk/detector-framework/pom.xml
projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java
projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java
projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/geometry/subdetector/HPSEcal3Test.java
projects/lcsim/trunk/detector-framework/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml
Modified: projects/lcsim/trunk/detector-framework/pom.xml
=============================================================================
--- projects/lcsim/trunk/detector-framework/pom.xml (original)
+++ projects/lcsim/trunk/detector-framework/pom.xml Mon Feb 23 17:38:59 2015
@@ -28,6 +28,8 @@
<exclude>org/lcsim/detector/converter/compact/MultiLayerTrackerTest.java</exclude>
<exclude>org/lcsim/material/NuclearInteractionLengthTest.java</exclude>
<exclude>org/lcsim/material/BetheBlockTest.java</exclude>
+ <exclude>org/lcsim/geometry/subdetector/HPSEcal3Test.java</exclude>
+ <exclude>org/lcsim/detector/converter/compact/HPSEcalAPITest.java</exclude>
</excludes>
</configuration>
</plugin>
Modified: projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java (original)
+++ projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java Mon Feb 23 17:38:59 2015
@@ -15,8 +15,6 @@
* which includes access to time dependent conditions as well as DAQ setup information.
* @author Jeremy McCormick <[log in to unmask]>
*/
-// TODO: Add method for getting an EcalCrystal objects neighbors.
-// FIXME: Remove conditions. These should come directly from conditions objects instead.
public class EcalCrystal extends DetectorElement {
Hep3Vector positionFront;
@@ -47,11 +45,12 @@
public int getY() {
return getIdentifierHelper().getValue(getIdentifier(), "iy");
}
-
+
/**
* Get the global center position of the XY plane in the front of the crystal.
- * This is used in the recon clustering algorithm for the "corrected"
- * hit position, so it is best to cache it once used for performance purposes.
+ * This is used in the reconstruction clustering algorithm for determining the
+ * "corrected" hit position, so it is best to cache it once used, for performance
+ * purposes.
* @return The center position of the XY plane in the front of the crystal.
*/
public Hep3Vector getPositionFront() {
Modified: projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java (original)
+++ projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java Mon Feb 23 17:38:59 2015
@@ -10,6 +10,7 @@
import org.jdom.DataConversionException;
import org.jdom.Element;
+import org.lcsim.detector.IDetectorElement;
import org.lcsim.detector.ILogicalVolume;
import org.lcsim.detector.IPhysicalVolume;
import org.lcsim.detector.IRotation3D;
@@ -47,35 +48,36 @@
IIdentifierHelper helper;
IIdentifierDictionary dict;
- private static class CrystalRange {
- int ixmin;
- int ixmax;
- int iymin;
- int iymax;
+ static class CrystalRange {
+
+ int xIndexMin;
+ int xIndexMax;
+ int yIndexMin;
+ int yIndexMax;
CrystalRange(Element elem) throws Exception {
- ixmin = ixmax = iymin = iymax = 0;
+ xIndexMin = xIndexMax = yIndexMin = yIndexMax = 0;
if (elem.getAttribute("ixmin") != null) {
- ixmin = elem.getAttribute("ixmin").getIntValue();
+ xIndexMin = elem.getAttribute("ixmin").getIntValue();
} else {
throw new RuntimeException("Missing ixmin parameter.");
}
if (elem.getAttribute("ixmax") != null) {
- ixmax = elem.getAttribute("ixmax").getIntValue();
+ xIndexMax = elem.getAttribute("ixmax").getIntValue();
} else {
throw new RuntimeException("Missing ixmax parameter.");
}
if (elem.getAttribute("iymin") != null) {
- iymin = elem.getAttribute("iymin").getIntValue();
+ yIndexMin = elem.getAttribute("iymin").getIntValue();
} else {
throw new RuntimeException("Missing ixmax parameter.");
}
if (elem.getAttribute("iymax") != null) {
- iymax = elem.getAttribute("iymax").getIntValue();
+ yIndexMax = elem.getAttribute("iymax").getIntValue();
} else {
throw new RuntimeException("Missing iymax parameter.");
}
@@ -86,7 +88,7 @@
if (ranges.size() == 0)
return true;
for (CrystalRange range : ranges) {
- if ((ix >= range.ixmin && ix <= range.ixmax) && ((iy >= range.iymin) && (iy <= range.iymax))) {
+ if ((ix >= range.xIndexMin && ix <= range.xIndexMax) && ((iy >= range.yIndexMin) && (iy <= range.yIndexMax))) {
return false;
}
@@ -175,6 +177,11 @@
throw new RuntimeException(x);
}
}
+
+ if (!ranges.isEmpty()) {
+ // FIXME: Assumes single range of removed crystals.
+ ((HPSEcalDetectorElement)subdet.getDetectorElement()).setBeamGapIndices(ranges.get(0));
+ }
// Setup crystal logical volume.
Trd crystalTrap = new Trd("crystal_trap", dx1, dx2, dy1, dy2, dz);
@@ -321,7 +328,7 @@
// Increment running Y totals.
ycorrtot += ycorr;
zcorrtoty += zcorry;
- }
+ }
}
/**
@@ -346,4 +353,10 @@
public Class getSubdetectorType() {
return HPSEcal3.class;
}
+
+ public IDetectorElement makeSubdetectorDetectorElement(Detector detector, Subdetector subdetector) {
+ IDetectorElement subdetectorDE = new HPSEcalDetectorElement(subdetector.getName(), detector.getDetectorElement());
+ subdetector.setDetectorElement(subdetectorDE);
+ return subdetectorDE;
+ }
}
Added: projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java (added)
+++ projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java Mon Feb 23 17:38:59 2015
@@ -0,0 +1,110 @@
+package org.lcsim.detector.converter.compact;
+
+import hep.physics.vec.Hep3Vector;
+
+import java.util.List;
+
+import org.lcsim.detector.identifier.IIdentifier;
+
+/**
+ * This is a geometry API for the HPS ECAL detector.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public interface HPSEcalAPI {
+
+ /**
+ * Get the maximum X index of the crystals.
+ * @return The maximum X index of the crystals.
+ */
+ int getXIndexMax();
+
+ /**
+ * Get the minimum X index of the crystals.
+ * @return The minimum X index of the crystals.
+ */
+ int getXIndexMin();
+
+ /**
+ * Get the maximum Y index of the crystals.
+ * @return The maximum Y index of the crystals.
+ */
+ int getYIndexMax();
+
+ /**
+ * Get the minimum Y index of the crystals.
+ * @return The minimum Y index of the crystals.
+ */
+ int getYIndexMin();
+
+ /**
+ * Get an array with all the valid X indices.
+ * @return An array with the X indices.
+ */
+ List<Integer> getXIndices();
+
+ /**
+ * Get an array with all the valid Y indices.
+ * @return An array with the Y indices.
+ */
+ List<Integer> getYIndices();
+
+ /**
+ * True if the given indices are located in the beam gap
+ * and so do not have crystals associated with them.
+ * @param x The X index.
+ * @param y The Y index.
+ * @return True if indices reference a position in the beam gap.
+ */
+ boolean isInBeamGap(int x, int y);
+
+ /**
+ * Get the crystal at the given indices or null if it does not exist.
+ * @param x The X index.
+ * @param y The Y index.
+ * @return The crystal at the given indices or null if it does not exist.
+ */
+ EcalCrystal getCrystal(int x, int y);
+
+ /**
+ * Get the crystal with the given ID or null if it does not exist
+ * @param id The packed ID of the crystal.
+ * @return The packed ID of the crystal.
+ */
+ EcalCrystal getCrystal(IIdentifier id);
+
+ /**
+ * Get the crystal at the given position in global coordinates or null if position
+ * is not inside a crystal's volume.
+ * @param position The position of the crystal.
+ * @return The crystal at the given position or null if position is not inside crystal.
+ */
+ EcalCrystal getCrystal(Hep3Vector position);
+
+ /**
+ * Get the list of crystal objects.
+ * @return The list of crystal objects.
+ */
+ List<EcalCrystal> getCrystals();
+
+ /**
+ * Get a row of crystals from the Y index.
+ * @param y The Y index.
+ * @return The row of crystals.
+ */
+ List<EcalCrystal> getRow(int y);
+
+ /**
+ * Get a column of crystals from the X index.
+ * @param x The X index.
+ * @return The column of crystals.
+ */
+ List<EcalCrystal> getColumn(int x);
+
+ /**
+ * Get the neighbors of a crystal.
+ * @param crystal A crystal object.
+ * @return The list of neighbor objects.
+ */
+ List<EcalCrystal> getNeighbors(EcalCrystal crystal);
+}
Added: projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java (added)
+++ projects/lcsim/trunk/detector-framework/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java Mon Feb 23 17:38:59 2015
@@ -0,0 +1,299 @@
+package org.lcsim.detector.converter.compact;
+
+import hep.physics.vec.Hep3Vector;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IDetectorElementContainer;
+import org.lcsim.detector.converter.compact.HPSEcal3Converter.CrystalRange;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+
+/**
+ * <p>
+ * This is an implementation of a basic geometry API for the HPS ECAL.
+ * <p>
+ * The neighboring API and conventions are based on the page 7 diagram from the
+ * <a href="https://wiki.jlab.org/hps-run/images/f/f4/Ecal_manual_annex.pdf">ECAL Manual Annex</a>
+ * in which the viewpoint is from the beam towards the detector.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @see HPSEcalAPI
+ * @see EcalCrystal
+ * @see org.lcsim.detector.IDetectorElement
+ * @see SubdetectorDetectorElement
+ */
+public final class HPSEcalDetectorElement extends SubdetectorDetectorElement implements HPSEcalAPI {
+
+ Map<EcalCrystal, List<EcalCrystal>> neighborMap;
+
+ int xIndexMax = Integer.MIN_VALUE;
+ int xIndexMin = Integer.MAX_VALUE;
+ int yIndexMax = Integer.MIN_VALUE;
+ int yIndexMin = Integer.MAX_VALUE;
+
+ List<Integer> xIndices;
+ List<Integer> yIndices;
+
+ CrystalRange beamGap;
+
+ public HPSEcalDetectorElement(String name, IDetectorElement parent) {
+ super(name, parent);
+ }
+
+ /**
+ * Set the index range for the beam gap.
+ * @param beamGap The beam gap index range.
+ */
+ void setBeamGapIndices(CrystalRange beamGap) {
+ this.beamGap = beamGap;
+ }
+
+ @Override
+ public int getXIndexMax() {
+ return xIndexMax;
+ }
+
+ @Override
+ public int getXIndexMin() {
+ return xIndexMin;
+ }
+
+ @Override
+ public int getYIndexMax() {
+ return yIndexMax;
+ }
+
+ @Override
+ public int getYIndexMin() {
+ return yIndexMin;
+ }
+
+ @Override
+ public List<Integer> getXIndices() {
+ return Collections.unmodifiableList(xIndices);
+ }
+
+ @Override
+ public List<Integer> getYIndices() {
+ return Collections.unmodifiableList(yIndices);
+ }
+
+ @Override
+ public boolean isInBeamGap(int xIndex, int yIndex) {
+ if((xIndex >= beamGap.xIndexMin && xIndex <= beamGap.xIndexMax) &&
+ (yIndex >= beamGap.yIndexMin && yIndex <= beamGap.yIndexMax)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public List<EcalCrystal> getRow(int yIndex) {
+ List<EcalCrystal> row = new ArrayList<EcalCrystal>();
+ for (int ix = xIndexMin; ix <= xIndexMax; ix++) {
+ if (ix == 0)
+ continue;
+ EcalCrystal crystal = getCrystal(ix, yIndex);
+ if (crystal != null) {
+ row.add(crystal);
+ }
+ }
+ return row;
+ }
+
+ @Override
+ public List<EcalCrystal> getColumn(int xIndex) {
+ List<EcalCrystal> column = new ArrayList<EcalCrystal>();
+ for (int iy = yIndexMin; iy <= yIndexMax; iy++) {
+ if (iy == 0)
+ continue;
+ EcalCrystal crystal = getCrystal(xIndex, iy);
+ if (crystal != null) {
+ column.add(crystal);
+ }
+ }
+ return column;
+ }
+
+ @Override
+ public EcalCrystal getCrystal(int xIndex, int yIndex) {
+ IIdentifierHelper helper = getIdentifierHelper();
+ IExpandedIdentifier expId = helper.createExpandedIdentifier();
+ expId.setValue(helper.getFieldIndex("ix"), xIndex);
+ expId.setValue(helper.getFieldIndex("iy"), yIndex);
+ expId.setValue(helper.getFieldIndex("system"), getSystemID());
+ return getCrystal(helper.pack(expId));
+ }
+
+ @Override
+ public EcalCrystal getCrystal(IIdentifier id) {
+ IDetectorElementContainer de = findDetectorElement(id);
+ if (de == null || de.isEmpty()) {
+ return null;
+ } else {
+ return (EcalCrystal) de.get(0);
+ }
+ }
+
+ @Override
+ public EcalCrystal getCrystal(Hep3Vector position) {
+ IDetectorElement de = findDetectorElement(position);
+ if (de instanceof EcalCrystal) {
+ return (EcalCrystal) de;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public List<EcalCrystal> getNeighbors(EcalCrystal crystal) {
+ return neighborMap.get(crystal);
+ }
+
+ @Override
+ public List<EcalCrystal> getCrystals() {
+ return findDescendants(EcalCrystal.class);
+ }
+
+ @Override
+ public void initialize() {
+ computeIndexRanges();
+ createNeighborMap();
+ }
+
+ void computeIndexRanges() {
+ for (EcalCrystal crystal : getCrystals()) {
+ if (crystal.getX() > xIndexMax) {
+ xIndexMax = crystal.getX();
+ }
+ if (crystal.getX() < xIndexMin) {
+ xIndexMin = crystal.getX();
+ }
+ if (crystal.getY() > yIndexMax) {
+ yIndexMax = crystal.getY();
+ }
+ if (crystal.getY() < yIndexMin) {
+ yIndexMin = crystal.getY();
+ }
+ }
+ //System.out.println("computed index boundaries ...");
+ //System.out.println("maxIndexX = " + xIndexMax);
+ //System.out.println("minIndexX = " + xIndexMin);
+ //System.out.println("maxIndexY = " + yIndexMax);
+ //System.out.println("minIndexY = " + yIndexMin);
+
+ xIndices = new ArrayList<Integer>();
+ for (int ix = xIndexMin; ix <= xIndexMax; ix++) {
+ if (ix == 0)
+ continue;
+ //System.out.println("adding ix = " + ix);
+ xIndices.add(ix);
+ }
+
+ yIndices = new ArrayList<Integer>();
+ for (int iy = yIndexMin; iy <= yIndexMax; iy++) {
+ if (iy == 0)
+ continue;
+ //System.out.println("adding iy = " + iy);
+ yIndices.add(iy);
+ }
+ }
+
+ // Constants for neighboring, relative to the beam direction as per diagram.
+ enum NeighborDirection {
+ NORTH,
+ NORTHEAST,
+ EAST,
+ SOUTHEAST,
+ SOUTH,
+ SOUTHWEST,
+ WEST,
+ NORTHWEST
+ }
+
+ /**
+ * Create a map of a crystal to its adjacent neighbors in all eight cardinal directions.
+ * Non-existent crystals are filtered out if the the geometry object does not exist,
+ * which automatically takes care of edge crystals and missing crystals from the beam gap
+ * without explicitly needing to check those indices for validity.
+ */
+ void createNeighborMap() {
+ neighborMap = new HashMap<EcalCrystal, List<EcalCrystal>>();
+ for (EcalCrystal crystal : getCrystals()) {
+ //System.out.println("find neighbors for " + crystal.getName() + " @ " + crystal.getX() + " " + crystal.getY());
+ List<EcalCrystal> neighborCrystals = new ArrayList<EcalCrystal>();
+ for (NeighborDirection neighborDirection : NeighborDirection.values()) {
+ int[] xy = getNeighborIndices(crystal, neighborDirection);
+ EcalCrystal neighborCrystal = getCrystal(xy[0], xy[1]);
+ if (neighborCrystal != null) {
+ //System.out.println(" adding neighbor @ " + neighborCrystal.getX() + " " + neighborCrystal.getY());
+ neighborCrystals.add(neighborCrystal);
+ }
+ }
+ neighborMap.put(crystal, neighborCrystals);
+ }
+ }
+
+ /**
+ * Get the neighbor indices of a crystal.
+ * @param crystal The ECAL crystal geometry object.
+ * @param direction The direction of the neighbor from integer encoding.
+ * @return The neighbor indices.
+ */
+ int[] getNeighborIndices(EcalCrystal crystal, NeighborDirection direction) {
+ int[] xy = new int[2];
+ int ix = crystal.getX();
+ int iy = crystal.getY();
+ switch (direction) {
+ case NORTH:
+ xy[0] = ix;
+ xy[1] = iy + 1;
+ break;
+ case NORTHEAST:
+ xy[0] = ix - 1;
+ if (xy[0] == 0) xy[0] = -1;
+ xy[1] = iy + 1;
+ break;
+ case EAST:
+ xy[0] = ix - 1;
+ if (xy[0] == 0) xy[0] = -1;
+ xy[1] = iy;
+ break;
+ case SOUTHEAST:
+ xy[0] = ix - 1;
+ if (xy[0] == 0) xy[0] = -1;
+ xy[1] = iy - 1;
+ break;
+ case SOUTH:
+ xy[0] = ix;
+ xy[1] = iy - 1;
+ break;
+ case SOUTHWEST:
+ xy[0] = ix + 1;
+ if (xy[0] == 0) xy[0] = 1;
+ xy[1] = iy - 1;
+ break;
+ case WEST:
+ xy[0] = ix + 1;
+ if (xy[0] == 0) xy[0] = 1;
+ xy[1] = iy;
+ break;
+ case NORTHWEST:
+ xy[0] = ix + 1;
+ if (xy[0] == 0) xy[0] = 1;
+ xy[1] = iy + 1;
+ break;
+ }
+ return xy;
+ }
+
+}
Added: projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java (added)
+++ projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java Mon Feb 23 17:38:59 2015
@@ -0,0 +1,73 @@
+package org.lcsim.detector.converter.compact;
+
+import java.io.InputStream;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.GeometryReader;
+
+/**
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class HPSEcalAPITest extends TestCase {
+
+ public void testHPSEcalAPI() throws Exception {
+ GeometryReader geometryReader = new GeometryReader();
+ InputStream in = getClass().getResourceAsStream("/org/lcsim/geometry/subdetector/HPSEcal3Test.xml");
+ Detector detector = geometryReader.read(in);
+
+ HPSEcalDetectorElement ecal = (HPSEcalDetectorElement)detector.getSubdetector("Ecal").getDetectorElement();
+
+ HPSEcalAPI api = (HPSEcalAPI) ecal;
+
+ assertEquals("The max X index is wrong.", 23, api.getXIndexMax());
+ assertEquals("The min X index is wrong.", -23, api.getXIndexMin());
+ assertEquals("The max Y index is wrong.", 5, api.getYIndexMax());
+ assertEquals("The min Y index is wrong.", -5, api.getYIndexMin());
+
+ for (Integer yIndex : api.getYIndices()) {
+ if (yIndex == 0) {
+ System.out.println("skipping yIndex = 0");
+ continue;
+ }
+ for (Integer xIndex : api.getXIndices()) {
+ System.out.println("checking crystal " + xIndex + ", " + yIndex);
+ if (xIndex == 0) {
+ System.out.println("skipping xIndex = 0");
+ continue;
+ }
+ if((yIndex == 1 || yIndex == -1) && (xIndex <= -2 && xIndex >= -10)) {
+ System.out.println("crystal " + xIndex + ", " + yIndex + " should be in the gap");
+ assertTrue("Indices should be in gap: " + xIndex + ", " + yIndex, api.isInBeamGap(xIndex, yIndex));
+ // Crystal is in the beam gap.
+ continue;
+ }
+ EcalCrystal crystal = api.getCrystal(xIndex, yIndex);
+ assertNotNull("Failed to find crystal at ix = " + xIndex + ", iy = " + yIndex, crystal);
+ }
+ }
+
+ for (Integer yIndex : api.getYIndices()) {
+ List<EcalCrystal> row = api.getRow(yIndex);
+ System.out.println("found " + row.size() + " crystals in row " + yIndex);
+ if (Math.abs(yIndex) != 1) {
+ assertEquals("Wrong number of crystals in row.", 46, row.size());
+ } else {
+ assertEquals("Wrong number of crystals in row.", 37, row.size());
+ }
+ }
+
+ for (Integer xIndex : api.getXIndices()) {
+ List<EcalCrystal> column = api.getColumn(xIndex);
+ System.out.println("found " + column.size() + " crystals in column " + xIndex);
+ if (xIndex > -2 || xIndex < -10) {
+ assertEquals("Wrong number of crystals in column.", 10, column.size());
+ } else {
+ assertEquals("Wrong number of crystals in column.", 8, column.size());
+ }
+ }
+ }
+}
Modified: projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/geometry/subdetector/HPSEcal3Test.java
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/geometry/subdetector/HPSEcal3Test.java (original)
+++ projects/lcsim/trunk/detector-framework/src/test/java/org/lcsim/geometry/subdetector/HPSEcal3Test.java Mon Feb 23 17:38:59 2015
@@ -9,6 +9,8 @@
import org.lcsim.detector.IDetectorElement;
import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.converter.compact.EcalCrystal;
+import org.lcsim.detector.converter.compact.HPSEcalDetectorElement;
import org.lcsim.detector.identifier.IIdentifierHelper;
import org.lcsim.geometry.Detector;
import org.lcsim.geometry.GeometryReader;
@@ -16,8 +18,11 @@
import org.lcsim.util.test.TestUtil.TestOutputFile;
/**
+ * <p>
* Test conversion of detector type {@link org.lcsim.geometry.subdetector.HPSEcal3}
* to LCDD, Heprep, and in-memory Java objects.
+ * <p>
+ * Also do a basic check of crystal object neighboring.
*
* @author Jeremy McCormick <[log in to unmask]>
*/
@@ -45,13 +50,45 @@
Detector detector = geometryReader.read(in);
System.out.println("built detector " + detector.getName());
- IDetectorElement de = detector.getSubdetector("ECAL").getDetectorElement();
+ IDetectorElement de = detector.getSubdetector("Ecal").getDetectorElement();
System.out.println("ECAL has " + de.getChildren().size() + " crystals.");
IIdentifierHelper helper = de.getIdentifierHelper();
for (IDetectorElement crystal : de.getChildren()) {
IGeometryInfo geometry = crystal.getGeometry();
System.out.println(crystal.getName() + " - " + helper.unpack(crystal.getIdentifier()) + " @ " + geometry.getPosition());
+ }
+ }
+
+ public void testNeighbors() throws Exception {
+ GeometryReader geometryReader = new GeometryReader();
+ InputStream in = getClass().getResourceAsStream("/org/lcsim/geometry/subdetector/HPSEcal3Test.xml");
+ Detector detector = geometryReader.read(in);
+
+ HPSEcalDetectorElement ecal = (HPSEcalDetectorElement)detector.getSubdetector("Ecal").getDetectorElement();
+
+ for (EcalCrystal crystal : ecal.getCrystals()) {
+ System.out.println(crystal.getName() + " @ " + crystal.getX() + " " + crystal.getY() + " has neighbors ...");
+ // Check this crystal object is valid.
+ checkValid(crystal);
+ for (EcalCrystal neighbor : ecal.getNeighbors(crystal)) {
+ System.out.println(" " + neighbor.getX() + " " + neighbor.getY());
+ // Check that each neighbor is valid.
+ checkValid(neighbor);
+ }
}
-
+ }
+
+ void checkValid(EcalCrystal crystal) {
+ int ix = crystal.getX();
+ int iy = crystal.getY();
+ if (Math.abs(ix) > 23) throw new RuntimeException("ix is invalid: " + ix);
+ if (Math.abs(iy) > 5) throw new RuntimeException("iy is invalid: " + iy);
+ if (ix == 0) throw new RuntimeException("ix is zero");
+ if (iy == 0) throw new RuntimeException("iy is zero");
+ if (Math.abs(iy) == 1) {
+ if (ix <= -2 && ix >= -10) {
+ throw new RuntimeException("crystal " + ix + " " + iy + " is in beam gap!");
+ }
+ }
}
}
Modified: projects/lcsim/trunk/detector-framework/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml
=============================================================================
--- projects/lcsim/trunk/detector-framework/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml (original)
+++ projects/lcsim/trunk/detector-framework/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml Mon Feb 23 17:38:59 2015
@@ -11,9 +11,11 @@
<constant name="tracking_region_min" value="5.0*cm" />
<constant name="tracking_region_zmax" value="100.0*cm" />
<!-- ECal placement parameters -->
- <constant name="ecal_front" value="13.3/2*mm" />
+ <constant name="beam_angle" value="0.03052"/>
+ <constant name="ecal_front" value="13.3/2*mm" />
<constant name="ecal_back" value="16/2*mm" />
<constant name="ecal_z" value="160/2*mm" />
+ <constant name="ecal_dface" value="139.3*cm"/>
</define>
<materials>
<material name="LeadTungstate">
@@ -24,6 +26,18 @@
</material>
</materials>
<detectors>
+
+ <detector id="13" name="Ecal" type="HPSEcal3" insideTrackingVolume="false" readout="EcalHits">
+ <comment>The crystal ECal</comment>
+ <material name="LeadTungstate" />
+ <dimensions x1="ecal_front" y1="ecal_front" x2="ecal_back" y2="ecal_back" z="ecal_z" />
+ <layout beamgap="20.0*mm" nx="46" ny="5" dface="ecal_dface">
+ <remove ixmin="-10" ixmax="-2" iymin="-1" iymax="1" />
+ <top dx="ecal_dface*tan(beam_angle)" dy="0." dz="0."/>
+ <bottom dx="ecal_dface*tan(beam_angle)" dy="0." dz="0."/>
+ </layout>
+ </detector>
+<!--
<detector id="2" name="ECAL" type="HPSEcal3" insideTrackingVolume="false" readout="ECAL_HITS">
<material name="LeadTungstate" />
<dimensions x1="ecal_front" y1="ecal_front" x2="ecal_back" y2="ecal_back" z="ecal_z" />
@@ -31,9 +45,10 @@
<remove ixmin="2" ixmax="7" iymin="-1" iymax="1" />
</layout>
</detector>
+ -->
</detectors>
<readouts>
- <readout name="ECAL_HITS">
+ <readout name="EcalHits">
<segmentation type="GridXYZ" gridSizeX="0.0" gridSizeY="0.0" gridSizeZ="0.0" />
<id>system:6,side:-2,layer:4,ix:-8,iy:-6</id>
</readout>
########################################################################
Use REPLY-ALL to reply to list
To unsubscribe from the LCDET-SVN list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCDET-SVN&A=1
|