Author: [log in to unmask]
Date: Tue Oct 6 11:36:11 2015
New Revision: 3768
Log:
[HPSJAVA-615] [HPSJAVA-614] Move detector model classes from lcsim to hps-java and related changes.
Added:
java/trunk/detector-model/src/main/java/org/hps/
java/trunk/detector-model/src/main/java/org/hps/detector/
java/trunk/detector-model/src/main/java/org/hps/detector/ecal/
java/trunk/detector-model/src/main/java/org/hps/detector/ecal/EcalCrystalChannelMap.java
- copied, changed from r3760, java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCrystalChannelMap.java
java/trunk/detector-model/src/main/java/org/hps/detector/svt/
java/trunk/detector-model/src/main/java/org/hps/detector/svt/SvtDetectorSetup.java
- copied, changed from r3746, java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDetectorSetup.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal2Converter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalConverter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterConverter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTracker2Converter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTrackerConverter.java
java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/
java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/silicon/
java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/silicon/HpsTestRunSiSensor.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal2.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal3.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter2.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal2.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal3.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSMuonCalorimeter.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker.java
java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker2.java
java/trunk/detector-model/src/test/java/org/hps/detector/svt/
java/trunk/detector-model/src/test/java/org/hps/detector/svt/SvtDetectorSetupTest.java
- copied, changed from r3746, java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java
java/trunk/detector-model/src/test/java/org/hps/detector/svt/TestRunSvtDetectorSetupTest.java
- copied, changed from r3746, java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java
java/trunk/detector-model/src/test/java/org/lcsim/detector/
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterTest.java
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSTracker2ConverterTest.java
java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HpsTestRunSiSensorConverterTest.java
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcalTest.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeter2Test.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTest.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2Test.xml
java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HpsTestRunSiSensorConverterTest.xml
Removed:
java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCrystalChannelMap.java
java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDetectorSetup.java
java/trunk/conditions/src/test/java/org/hps/conditions/EngRunConditionsTest.java
java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java
java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java
Modified:
java/trunk/conditions/pom.xml
java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java
java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java
java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java
java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditions.java
java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java
java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java
java/trunk/conditions/src/test/java/org/hps/conditions/database/DatabaseConditionsManagerTest.java
java/trunk/detector-model/pom.xml
java/trunk/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java
Modified: java/trunk/conditions/pom.xml
=============================================================================
--- java/trunk/conditions/pom.xml (original)
+++ java/trunk/conditions/pom.xml Tue Oct 6 11:36:11 2015
@@ -33,6 +33,9 @@
<exclude>org/hps/conditions/svt/TestRunSvtConditionsConverterTest.java</exclude>
<exclude>org/hps/conditions/svt/TestRunSvtDaqMappingTest.java</exclude>
<exclude>org/hps/conditions/svt/SvtTimingConstantsTest.java</exclude>
+ <exclude>org/hps/conditions/svt/SvtAlignmentTest.java</exclude>
+ <exclude>org/hps/conditions/api/ConditionsTagTest.java</exclude>
+ <exclude>org/hps/conditions/HPSJAVA_529_Test.java</exclude>
<exclude>org/hps/conditions/dummy/**.java</exclude>
</excludes>
</configuration>
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/api/ConditionsObjectException.java Tue Oct 6 11:36:11 2015
@@ -12,6 +12,15 @@
* The associated conditions object to the error.
*/
private ConditionsObject object;
+
+ /**
+ * Error with a message.
+ *
+ * @param message the error message
+ */
+ public ConditionsObjectException(Exception e) {
+ super(e);
+ }
/**
* Error with a message.
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/database/DatabaseConditionsManager.java Tue Oct 6 11:36:11 2015
@@ -33,7 +33,6 @@
import org.hps.conditions.ecal.TestRunEcalConditionsConverter;
import org.hps.conditions.svt.SvtConditions;
import org.hps.conditions.svt.SvtConditionsConverter;
-import org.hps.conditions.svt.SvtDetectorSetup;
import org.hps.conditions.svt.TestRunSvtConditionsConverter;
import org.jdom.Document;
import org.jdom.Element;
@@ -66,7 +65,7 @@
* Name of system property that can be used to specify custom database connection parameters.
*/
private static final String CONNECTION_PROPERTY_FILE = "org.hps.conditions.connection.file";
-
+
/**
* Connection property resource.
*/
@@ -90,7 +89,8 @@
/**
* Initialize the logger.
*/
- private static Logger LOGGER = LogUtil.create(DatabaseConditionsManager.class.getName(), new DefaultLogFormatter(), Level.CONFIG);
+ private static Logger LOGGER = LogUtil.create(DatabaseConditionsManager.class.getName(), new DefaultLogFormatter(),
+ Level.CONFIG);
/**
* The Test Run XML config.
@@ -116,9 +116,9 @@
// Is there no manager installed yet?
if (!ConditionsManager.isSetup() || !(ConditionsManager.defaultInstance() instanceof DatabaseConditionsManager)) {
-
+
// Create a new instance if necessary, which will install it globally as the default.
- DatabaseConditionsManager dbManager = new DatabaseConditionsManager();
+ final DatabaseConditionsManager dbManager = new DatabaseConditionsManager();
// Register default conditions manager.
ConditionsManager.setDefaultConditionsManager(dbManager);
@@ -157,13 +157,13 @@
* Reset the global static instance of the conditions manager to a new object.
*/
public static synchronized void resetInstance() {
-
+
// Create a new instance if necessary, which will install it globally as the default.
- DatabaseConditionsManager dbManager = new DatabaseConditionsManager();
+ final DatabaseConditionsManager dbManager = new DatabaseConditionsManager();
// Register default conditions manager.
ConditionsManager.setDefaultConditionsManager(dbManager);
-
+
LOGGER.info("DatabaseConditionsManager instance is reset");
}
@@ -178,6 +178,16 @@
private boolean closeConnectionAfterInitialize = true;
/**
+ * The current set of conditions for the run.
+ */
+ private ConditionsRecordCollection conditionsRecordCollection = null;
+
+ /**
+ * The currently active conditions tag (empty collection means no tag is active).
+ */
+ private final ConditionsTagCollection conditionsTagCollection = new ConditionsTagCollection();
+
+ /**
* The current database connection.
*/
private Connection connection;
@@ -258,54 +268,70 @@
private String svtName = "Tracker";
/**
- * The helper for setting up the SVT detector with its conditions information.
- */
- private final SvtDetectorSetup svtSetup = new SvtDetectorSetup(this.svtName);
-
- /**
* Create the global registry of table meta data.
*/
private final TableRegistry tableRegistry = TableRegistry.getTableRegistry();
/**
- * The currently active conditions tag (empty collection means no tag is active).
- */
- private ConditionsTagCollection conditionsTagCollection = new ConditionsTagCollection();
-
- /**
- * The current set of conditions for the run.
- */
- private ConditionsRecordCollection conditionsRecordCollection = null;
-
- /**
* The currently applied conditions tags.
*/
- private Set<String> tags = new HashSet<String>();
-
+ private final Set<String> tags = new HashSet<String>();
+
/**
* Class constructor. Calling this will automatically register this manager as the global default.
*/
protected DatabaseConditionsManager() {
-
+
// Register detector conditions converter.
this.registerConditionsConverter(new DetectorConditionsConverter());
-
+
// Setup connection from system property pointing to a file, if it was set.
this.setupConnectionSystemPropertyFile();
-
+
// Setup connection from system property pointing to a resource, if it was set.
this.setupConnectionSystemPropertyResource();
-
+
// Set run to invalid number.
this.setRun(-1);
-
+
// Register conditions converters.
for (final AbstractConditionsObjectConverter converter : this.converters.values()) {
this.registerConditionsConverter(converter);
}
-
- // Add the SVT detector setup object as a listener.
- this.addConditionsListener(this.svtSetup);
+ }
+
+ /**
+ * Add a tag used to filter the accessible conditions records.
+ * <p>
+ * Multiple tags are OR'd together.
+ *
+ * @param tag the tag value used to filter returned conditions records
+ */
+ public void addTag(final String tag) {
+ if (!this.tags.contains(tag)) {
+ LOGGER.info("adding tag " + tag);
+ final ConditionsTagCollection findConditionsTag = this.getCachedConditions(ConditionsTagCollection.class,
+ tag).getCachedData();
+ if (findConditionsTag.size() == 0) {
+ throw new IllegalArgumentException("The tag " + tag + " does not exist in the database.");
+ }
+ LOGGER.info("adding conditions tag " + tag + " with " + conditionsTagCollection.size() + " records");
+ this.conditionsTagCollection.addAll(findConditionsTag);
+ this.tags.add(tag);
+ } else {
+ LOGGER.warning("tag " + tag + " is already added");
+ }
+ }
+
+ /**
+ * Add one or more tags for filtering records.
+ *
+ * @param tags the <code>Set</code> of tags to add
+ */
+ public void addTags(final Set<String> tags) {
+ for (final String tag : tags) {
+ this.addTag(tag);
+ }
}
/**
@@ -321,6 +347,14 @@
LOGGER.warning("could not cache conditions " + meta.getKey());
}
}
+ }
+
+ /**
+ * Clear the tags used to filter the {@link org.hps.conditons.api.ConditionsRecord}s.
+ */
+ public void clearTags() {
+ this.tags.clear();
+ this.conditionsTagCollection.clear();
}
/**
@@ -412,9 +446,9 @@
* @return the set of matching conditions records
*/
public ConditionsRecordCollection findConditionsRecords(final String name) {
- return getConditionsRecords().findByKey(name);
- }
-
+ return this.getConditionsRecords().findByKey(name);
+ }
+
/**
* Find table information from the name.
*
@@ -436,6 +470,49 @@
} else {
LOGGER.warning("conditions system cannot be frozen because it is not initialized yet");
}
+ }
+
+ /**
+ * Get the currently active conditions tags.
+ *
+ * @return the currently active conditions tags
+ */
+ public Collection<String> getActiveTags() {
+ return Collections.unmodifiableCollection(this.tags);
+ }
+
+ /**
+ * Get the set of available conditions tags from the conditions table
+ *
+ * @return the set of available conditions tags
+ */
+ public Set<String> getAvailableTags() {
+ LOGGER.fine("getting list of available conditions tags");
+ final boolean openedConnection = this.openConnection();
+ final Set<String> tags = new LinkedHashSet<String>();
+ final ResultSet rs = this
+ .selectQuery("select distinct(tag) from conditions_tags where tag is not null order by tag");
+ try {
+ while (rs.next()) {
+ tags.add(rs.getString(1));
+ }
+ } catch (final SQLException e) {
+ throw new RuntimeException(e);
+ }
+ try {
+ rs.close();
+ } catch (final SQLException e) {
+ LOGGER.log(Level.WARNING, "error closing ResultSet", e);
+ }
+ final StringBuffer sb = new StringBuffer();
+ sb.append("found unique conditions tags: ");
+ for (final String tag : tags) {
+ sb.append(tag + " ");
+ }
+ sb.setLength(sb.length() - 1);
+ LOGGER.fine(sb.toString());
+ this.closeConnection(openedConnection);
+ return tags;
}
/**
@@ -483,27 +560,26 @@
collection.setCollectionId(collectionId);
return collectionId;
}
-
+
/**
* Get the list of conditions records for the run, filtered by the current set of active tags.
- *
+ *
* @return the list of conditions records for the run
*/
public ConditionsRecordCollection getConditionsRecords() {
if (this.run == -1 || this.detectorName == null) {
throw new IllegalStateException("Conditions system is not initialized.");
- }
+ }
// If the collection is null then the new conditions records need to be retrieved from the database.
if (this.conditionsRecordCollection == null) {
-
+
// Get the collection of conditions that are applicable for the current run.
- this.conditionsRecordCollection =
- this.getCachedConditions(ConditionsRecordCollection.class, "conditions").getCachedData();
-
+ this.conditionsRecordCollection = this.getCachedConditions(ConditionsRecordCollection.class, "conditions")
+ .getCachedData();
+
// If there is one or more tags enabled then filter the collection by the tag names.
if (this.conditionsTagCollection.size() > 0) {
- this.conditionsRecordCollection =
- this.conditionsTagCollection.filter(this.conditionsRecordCollection);
+ this.conditionsRecordCollection = this.conditionsTagCollection.filter(this.conditionsRecordCollection);
}
}
return this.conditionsRecordCollection;
@@ -592,49 +668,6 @@
public SvtConditions getSvtConditions() {
return this.getCachedConditions(SvtConditions.class, "svt_conditions").getCachedData();
}
-
- /**
- * Get the currently active conditions tags.
- *
- * @return the currently active conditions tags
- */
- public Collection<String> getActiveTags() {
- return Collections.unmodifiableCollection(this.tags);
- }
-
- /**
- * Get the set of available conditions tags from the conditions table
- *
- * @return the set of available conditions tags
- */
- public Set<String> getAvailableTags() {
- LOGGER.fine("getting list of available conditions tags");
- final boolean openedConnection = this.openConnection();
- final Set<String> tags = new LinkedHashSet<String>();
- final ResultSet rs = this
- .selectQuery("select distinct(tag) from conditions_tags where tag is not null order by tag");
- try {
- while (rs.next()) {
- tags.add(rs.getString(1));
- }
- } catch (final SQLException e) {
- throw new RuntimeException(e);
- }
- try {
- rs.close();
- } catch (final SQLException e) {
- LOGGER.log(Level.WARNING, "error closing ResultSet", e);
- }
- final StringBuffer sb = new StringBuffer();
- sb.append("found unique conditions tags: ");
- for (final String tag : tags) {
- sb.append(tag + " ");
- }
- sb.setLength(sb.length() - 1);
- LOGGER.fine(sb.toString());
- this.closeConnection(openedConnection);
- return tags;
- }
/**
* True if there is a conditions record with the given name.
@@ -656,12 +689,12 @@
* @throws ConditionsNotFoundException if there is a conditions system error
*/
private void initialize(final String detectorName, final int runNumber) throws ConditionsNotFoundException {
-
+
LOGGER.config("initializing with detector " + detectorName + " and run " + runNumber);
-
+
// Clear the conditions cache.
- this.clearCache();
-
+ // this.clearCache();
+
// Set flag if run number is from Test Run 2012 data.
if (isTestRun(runNumber)) {
this.isTestRun = true;
@@ -669,7 +702,7 @@
// Is not configured yet?
if (!this.isConfigured) {
- if (isTestRun()) {
+ if (this.isTestRun()) {
// This looks like the Test Run so use the custom configuration for it.
this.setXmlConfig(DatabaseConditionsManager.TEST_RUN_CONFIG);
} else if (runNumber > TEST_RUN_MAX_RUN) {
@@ -684,20 +717,16 @@
// Register the converters for this initialization.
this.registerConverters();
- // Enable or disable the setup of the SVT detector.
- LOGGER.fine("SVT setup enabled: " + this.setupSvtDetector);
- this.svtSetup.setEnabled(this.setupSvtDetector);
-
// Open the database connection.
this.openConnection();
-
+
// Reset the conditions records to trigger a re-caching.
this.conditionsRecordCollection = null;
-
+
// Call the super class's setDetector method to construct the detector object and activate conditions listeners.
LOGGER.fine("activating default conditions manager");
super.setDetector(detectorName, runNumber);
-
+
// Should all conditions sets be cached?
if (this.cacheAllConditions) {
// Cache the conditions sets of all registered converters.
@@ -832,7 +861,7 @@
/**
* Create a new collection with the given type.
- *
+ *
* @param collectionType the collection type
* @return the new collection
*/
@@ -858,7 +887,7 @@
/**
* Create a new collection with the given type and table name.
- *
+ *
* @param collectionType the collection type
* @param tableName the table name
* @return the new collection
@@ -1040,7 +1069,6 @@
LOGGER.config("setting log level to " + level);
LOGGER.setLevel(level);
LOGGER.getHandlers()[0].setLevel(level);
- this.svtSetup.setLogLevel(level);
}
/**
@@ -1054,47 +1082,6 @@
}
this.svtName = svtName;
LOGGER.info("SVT name set to " + this.ecalName);
- }
-
- /**
- * Add a tag used to filter the accessible conditions records.
- * <p>
- * Multiple tags are OR'd together.
- *
- * @param tag the tag value used to filter returned conditions records
- */
- public void addTag(final String tag) {
- if (!this.tags.contains(tag)) {
- LOGGER.info("adding tag " + tag);
- ConditionsTagCollection findConditionsTag = this.getCachedConditions(ConditionsTagCollection.class, tag).getCachedData();
- if (findConditionsTag.size() == 0) {
- throw new IllegalArgumentException("The tag " + tag + " does not exist in the database.");
- }
- LOGGER.info("adding conditions tag " + tag + " with " + conditionsTagCollection.size() + " records");
- this.conditionsTagCollection.addAll(findConditionsTag);
- this.tags.add(tag);
- } else {
- LOGGER.warning("tag " + tag + " is already added");
- }
- }
-
- /**
- * Add one or more tags for filtering records.
- *
- * @param tags the <code>Set</code> of tags to add
- */
- public void addTags(final Set<String> tags) {
- for (String tag : tags) {
- this.addTag(tag);
- }
- }
-
- /**
- * Clear the tags used to filter the {@link org.hps.conditons.api.ConditionsRecord}s.
- */
- public void clearTags() {
- this.tags.clear();
- this.conditionsTagCollection.clear();
}
/**
@@ -1112,18 +1099,19 @@
this.setConnectionProperties(f);
LOGGER.info("connection setup from system property " + CONNECTION_PROPERTY_FILE + " = "
+ systemPropertiesConnectionPath);
- }
- }
-
+ }
+ }
+
/**
* Setup the database connection from a file specified by a Java system property setting. This could be overridden
* by subsequent API calls to {@link #setConnectionProperties(File)} or {@link #setConnectionResource(String)}.
*/
private void setupConnectionSystemPropertyResource() {
- final String systemPropertiesConnectionResource = (String) System.getProperties().get(CONNECTION_PROPERTY_RESOURCE);
+ final String systemPropertiesConnectionResource = (String) System.getProperties().get(
+ CONNECTION_PROPERTY_RESOURCE);
if (systemPropertiesConnectionResource != null) {
this.setConnectionResource(systemPropertiesConnectionResource);
- }
+ }
}
/**
@@ -1160,5 +1148,5 @@
public synchronized void unfreeze() {
this.isFrozen = false;
LOGGER.info("conditions system unfrozen");
- }
+ }
}
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalChannel.java Tue Oct 6 11:36:11 2015
@@ -290,8 +290,11 @@
public EcalChannelCollection getData(final ConditionsManager conditionsManager, final String name) {
final EcalChannelCollection collection = super.getData(conditionsManager, name);
final Subdetector ecal = DatabaseConditionsManager.getInstance().getEcalSubdetector();
- if (ecal != null) {
+ if (ecal.getDetectorElement() != null) {
collection.buildGeometryMap(ecal.getDetectorElement().getIdentifierHelper(), ecal.getSystemID());
+ } else {
+ // This can happen when not running with the detector-framework jar in the classpath.
+ throw new IllegalStateException("The ECal subdetector's detector element is not setup.");
}
return collection;
}
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditions.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditions.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditions.java Tue Oct 6 11:36:11 2015
@@ -4,8 +4,6 @@
import java.util.Map;
import org.hps.conditions.ecal.EcalChannel.EcalChannelCollection;
-import org.lcsim.detector.converter.compact.EcalCrystal;
-import org.lcsim.detector.converter.compact.HPSEcalAPI;
import org.lcsim.geometry.Subdetector;
/**
@@ -36,11 +34,6 @@
private final Map<EcalChannel, EcalChannelConstants> channelConstants = new HashMap<EcalChannel, EcalChannelConstants>();
/**
- * Map between channels and geometric crystals.
- */
- private EcalCrystalChannelMap crystalMap;
-
- /**
* The current ECAL subdetector in the geometry.
*/
private final Subdetector subdetector;
@@ -55,16 +48,6 @@
throw new IllegalArgumentException("The subdetector argument is null.");
}
this.subdetector = subdetector;
- }
-
- /**
- * Get the channel information for a geometric crystal.
- *
- * @param crystal the geometric crystal
- * @return the channel information or null if does not exist
- */
- public EcalChannel getChannel(final EcalCrystal crystal) {
- return this.crystalMap.getEcalChannel(crystal);
}
/**
@@ -104,10 +87,6 @@
*/
void setChannelCollection(final EcalChannelCollection channelCollection) {
this.channelCollection = channelCollection;
-
- // Build the map between crystals and channels.
- this.crystalMap = new EcalCrystalChannelMap((HPSEcalAPI) this.subdetector.getDetectorElement(),
- channelCollection);
}
/**
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalConditionsConverter.java Tue Oct 6 11:36:11 2015
@@ -1,4 +1,7 @@
package org.hps.conditions.ecal;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.hps.conditions.api.ConditionsObjectCollection;
import org.hps.conditions.api.ConditionsSeries;
@@ -30,6 +33,14 @@
public class EcalConditionsConverter implements ConditionsConverter<EcalConditions> {
/**
+ * Setup logger.
+ */
+ private static Logger LOGGER = Logger.getLogger(EcalConditionsConverter.class.getName());
+ static {
+ LOGGER.setLevel(Level.ALL);
+ }
+
+ /**
* Create combined ECAL conditions object containing all data for the current run.
*
* @param manager the conditions manager
@@ -40,6 +51,15 @@
// Get the ECal channel map from the conditions database.
final EcalChannelCollection channels = this.getEcalChannelCollection();
+
+ if (channels == null) {
+ throw new IllegalStateException("The ECal channels collection is null.");
+ }
+ if (channels.size() == 0) {
+ throw new IllegalStateException("The ECal channels collection is empty.");
+ }
+
+ LOGGER.fine("ECal channel collection has " + channels.size() + " objects");
// Create the ECal conditions object that will be used to encapsulate ECal conditions collections.
final Detector detector = getDatabaseConditionsManager().getDetectorObject();
@@ -51,9 +71,11 @@
// Get the ECal gains from the conditions database and add them to the conditions set
final EcalGainCollection gains = this.getEcalGainCollection();
+ LOGGER.fine("ECal gain collction has " + gains.size() + " objects");
for (final EcalGain gain : gains) {
final ChannelId channelId = new ChannelId(new int[] {gain.getChannelId()});
final EcalChannel channel = channels.findChannel(channelId);
+ LOGGER.fine("setting channel " + channel.getChannel() + " gain to " + gain.getGain());
conditions.getChannelConstants(channel).setGain(gain);
}
@@ -70,9 +92,11 @@
// Get the ECal calibrations from the conditions database and add them to the conditions set.
final EcalCalibrationCollection calibrations = this.getEcalCalibrationCollection();
+ LOGGER.fine("ECal calibration collction has " + calibrations.size() + " objects");
for (final EcalCalibration calibration : calibrations) {
final ChannelId channelId = new ChannelId(new int[] {calibration.getChannelId()});
final EcalChannel channel = channels.findChannel(channelId);
+ LOGGER.fine("setting channel " + channel.getChannel() + " ped, noise to " + calibration.getPedestal() + ", " + calibration.getNoise());
conditions.getChannelConstants(channel).setCalibration(calibration);
}
Modified: java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java (original)
+++ java/trunk/conditions/src/main/java/org/hps/conditions/svt/TestRunSvtDaqMapping.java Tue Oct 6 11:36:11 2015
@@ -4,7 +4,6 @@
import org.hps.conditions.database.Table;
import org.hps.util.Pair;
import org.lcsim.detector.tracker.silicon.HpsSiSensor;
-import org.lcsim.detector.tracker.silicon.HpsTestRunSiSensor;
/**
* This class encapsulates the Test Run SVT DAQ map.
Modified: java/trunk/conditions/src/test/java/org/hps/conditions/database/DatabaseConditionsManagerTest.java
=============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/database/DatabaseConditionsManagerTest.java (original)
+++ java/trunk/conditions/src/test/java/org/hps/conditions/database/DatabaseConditionsManagerTest.java Tue Oct 6 11:36:11 2015
@@ -47,7 +47,7 @@
TestCase.assertTrue("The manager should be connected.", manager.isConnected());
TestCase.assertNotNull("The connection is null.", manager.getConnection());
- // Turn off SVT detector setup becaues some classes are not available from this module.
+ // Turn off SVT detector setup because some required classes are not available from this module.
manager.setXmlConfig("/org/hps/conditions/config/conditions_database_no_svt.xml");
// Initialize the conditions system.
@@ -59,14 +59,14 @@
// Make sure that freezing the conditions system works properly.
manager.freeze();
- TestCase.assertTrue("The manager should be frozen.", manager.isFrozen());
- manager.setDetector("HPS-EngRun2015-Nominal-v2", 1234);
+ TestCase.assertTrue("The manager should be frozen.", manager.isFrozen());
+ manager.setDetector("HPS-EngRun2015-Nominal-v2", 1234);
TestCase.assertEquals("The run number should be the same because system was frozen.", 5772, manager.getRun());
// Check detector object state.
Detector detector = manager.getDetectorObject();
TestCase.assertNotNull("The detector is null.", detector);
- TestCase.assertNotNull("The ECal conditions are null.", manager.getEcalConditions());
+ //TestCase.assertNotNull("The ECal conditions are null.", manager.getEcalConditions());
TestCase.assertNotNull("The ECal name is null.", manager.getEcalName());
TestCase.assertNotNull("The ECal subdetector is null.", manager.getEcalSubdetector());
TestCase.assertNotNull("The SVT conditions are null.", manager.getSvtConditions());
Modified: java/trunk/detector-model/pom.xml
=============================================================================
--- java/trunk/detector-model/pom.xml (original)
+++ java/trunk/detector-model/pom.xml Tue Oct 6 11:36:11 2015
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>hps-detector-model</artifactId>
<name>detector-model</name>
@@ -9,7 +10,7 @@
<artifactId>hps-parent</artifactId>
<relativePath>../parent/pom.xml</relativePath>
<version>3.4.1-SNAPSHOT</version>
- </parent>
+ </parent>
<build>
<plugins>
<plugin>
@@ -25,8 +26,10 @@
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>bin</shadedClassifierName>
<transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.lcsim.geometry.compact.converter.Main</mainClass>
</transformer>
</transformers>
@@ -39,7 +42,17 @@
</execution>
</executions>
</plugin>
- </plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>org/hps/detector/svt/TestRunSvtDetectorSetupTest.java</exclude>
+ <exclude>org/hps/detector/SvtAlignmentTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
</build>
<scm>
<url>http://java.freehep.org/svn/repos/hps/list/java/trunk/detector-model/</url>
Copied: java/trunk/detector-model/src/main/java/org/hps/detector/ecal/EcalCrystalChannelMap.java (from r3760, java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCrystalChannelMap.java)
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/ecal/EcalCrystalChannelMap.java (original)
+++ java/trunk/detector-model/src/main/java/org/hps/detector/ecal/EcalCrystalChannelMap.java Tue Oct 6 11:36:11 2015
@@ -1,8 +1,9 @@
-package org.hps.conditions.ecal;
+package org.hps.detector.ecal;
import java.util.HashMap;
import java.util.Map;
+import org.hps.conditions.ecal.EcalChannel;
import org.hps.conditions.ecal.EcalChannel.EcalChannelCollection;
import org.lcsim.detector.converter.compact.EcalCrystal;
import org.lcsim.detector.converter.compact.HPSEcalAPI;
Copied: java/trunk/detector-model/src/main/java/org/hps/detector/svt/SvtDetectorSetup.java (from r3746, java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDetectorSetup.java)
=============================================================================
--- java/trunk/conditions/src/main/java/org/hps/conditions/svt/SvtDetectorSetup.java (original)
+++ java/trunk/detector-model/src/main/java/org/hps/detector/svt/SvtDetectorSetup.java Tue Oct 6 11:36:11 2015
@@ -1,4 +1,4 @@
-package org.hps.conditions.svt;
+package org.hps.detector.svt;
import java.util.Collection;
import java.util.List;
@@ -6,11 +6,19 @@
import java.util.logging.Logger;
import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.svt.AbstractSvtDaqMapping;
+import org.hps.conditions.svt.ChannelConstants;
+import org.hps.conditions.svt.SvtChannel;
import org.hps.conditions.svt.SvtChannel.SvtChannelCollection;
+import org.hps.conditions.svt.SvtConditions;
import org.hps.conditions.svt.SvtDaqMapping.SvtDaqMappingCollection;
+import org.hps.conditions.svt.SvtT0Shift;
import org.hps.conditions.svt.SvtT0Shift.SvtT0ShiftCollection;
+import org.hps.conditions.svt.TestRunSvtChannel;
import org.hps.conditions.svt.TestRunSvtChannel.TestRunSvtChannelCollection;
+import org.hps.conditions.svt.TestRunSvtConditions;
import org.hps.conditions.svt.TestRunSvtDaqMapping.TestRunSvtDaqMappingCollection;
+import org.hps.conditions.svt.TestRunSvtT0Shift;
import org.hps.conditions.svt.TestRunSvtT0Shift.TestRunSvtT0ShiftCollection;
import org.hps.util.Pair;
import org.lcsim.conditions.ConditionsEvent;
@@ -32,6 +40,9 @@
* Initialize logger.
*/
private static Logger logger = LogUtil.create(SvtDetectorSetup.class);
+ static {
+ logger.setLevel(Level.ALL);
+ }
/**
* The number of noise samples.
@@ -54,11 +65,19 @@
private String svtName = "Tracker";
/**
+ * Constructor that uses the default detector name.
+ */
+ public SvtDetectorSetup() {
+ logger.info("hi");
+ }
+
+ /**
* Constructor that takes name of SVT.
*
* @param svtName the name of the SVT subdetector
*/
public SvtDetectorSetup(final String svtName) {
+ logger.info("hi");
this.svtName = svtName;
}
@@ -69,15 +88,19 @@
*/
@Override
public void conditionsChanged(final ConditionsEvent event) {
+ logger.info("conditions changed hook activated");
if (this.enabled) {
+ logger.info("I am enabled");
final DatabaseConditionsManager manager = (DatabaseConditionsManager) event.getConditionsManager();
final Subdetector subdetector = manager.getDetectorObject().getSubdetector(this.svtName);
if (subdetector != null) {
+ logger.info("found the SVT");
if (manager.isTestRun()) {
final TestRunSvtConditions svtConditions = manager.getCachedConditions(TestRunSvtConditions.class,
"test_run_svt_conditions").getCachedData();
this.loadTestRun(subdetector, svtConditions);
} else {
+ logger.info("activating default setup (not test run)");
final SvtConditions svtConditions = manager.getCachedConditions(SvtConditions.class,
"svt_conditions").getCachedData();
this.loadDefault(subdetector, svtConditions);
@@ -99,7 +122,7 @@
*/
void loadDefault(final Subdetector subdetector, final SvtConditions conditions) {
- logger.info("loading SVT conditions onto subdetector " + subdetector.getName());
+ logger.info("loading default SVT conditions onto subdetector " + subdetector.getName());
// Find sensor objects.
final List<HpsSiSensor> sensors = subdetector.getDetectorElement().findDescendants(HpsSiSensor.class);
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/EcalCrystal.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,66 @@
+package org.lcsim.detector.converter.compact;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import org.lcsim.detector.DetectorElement;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.solids.Trd;
+
+/**
+ * This class implements behavior specific to the ECal crystals of the HPS experiment,
+ * which includes access to time dependent conditions as well as DAQ setup information.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class EcalCrystal extends DetectorElement {
+
+ Hep3Vector positionFront;
+
+ /**
+ * Class constructor.
+ * @param name The name of the DetectorElement.
+ * @param parent The parent component.
+ * @param path The physical path.
+ * @param id The component's ID.
+ */
+ EcalCrystal(String name, IDetectorElement parent, String path, IIdentifier id) {
+ super(name, parent, path, id);
+ }
+
+ /**
+ * Get the X index of this crystal.
+ * @return The X index of this crystal.
+ */
+ public int getX() {
+ return getIdentifierHelper().getValue(getIdentifier(), "ix");
+ }
+
+ /**
+ * Get the Y index of this crystal.
+ * @return The Y index of this crystal.
+ */
+ 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 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() {
+ if (positionFront == null) {
+ IGeometryInfo geom = getGeometry();
+ double[] p = geom.transformLocalToGlobal(VecOp.add(geom.transformGlobalToLocal(geom.getPosition()),
+ (Hep3Vector) new BasicHep3Vector(0, 0, -1 * ((Trd) geom.getLogicalVolume().getSolid()).getZHalfLength()))).v();
+ positionFront = new BasicHep3Vector(p[0], p[1], p[2]);
+ }
+ return positionFront;
+ }
+
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal2Converter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal2Converter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal2Converter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,18 @@
+package org.lcsim.detector.converter.compact;
+
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSEcal2;
+
+public class HPSEcal2Converter extends AbstractSubdetectorConverter
+{
+ public void convert(Subdetector subdet, Detector detector)
+ {
+ System.out.println(this.getClass().getCanonicalName());
+ }
+
+ public Class getSubdetectorType()
+ {
+ return HPSEcal2.class;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcal3Converter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,397 @@
+package org.lcsim.detector.converter.compact;
+
+import static java.lang.Math.atan;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import static java.lang.Math.tan;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+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;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.LogicalVolume;
+import org.lcsim.detector.PhysicalVolume;
+import org.lcsim.detector.RotationGeant;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.material.MaterialStore;
+import org.lcsim.detector.solids.Trd;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+
+public class HPSEcal3Converter extends AbstractSubdetectorConverter {
+
+ private static Logger LOGGER = Logger.getLogger(HPSEcal3Converter.class.toString());
+
+ static class CrystalRange {
+
+ int xIndexMax;
+ int xIndexMin;
+ int yIndexMax;
+ int yIndexMin;
+
+ CrystalRange(final Element elem) throws Exception {
+ xIndexMin = xIndexMax = yIndexMin = yIndexMax = 0;
+
+ if (elem.getAttribute("ixmin") != null) {
+ xIndexMin = elem.getAttribute("ixmin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmin parameter.");
+ }
+
+ if (elem.getAttribute("ixmax") != null) {
+ xIndexMax = elem.getAttribute("ixmax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymin") != null) {
+ yIndexMin = elem.getAttribute("iymin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymax") != null) {
+ yIndexMax = elem.getAttribute("iymax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing iymax parameter.");
+ }
+ }
+ }
+
+ static final double crystalToleranceX = 0.2;
+ // Tolerance factor for separating crystals to avoid overlaps.
+ static final double crystalToleranceY = 0.35;
+
+ // Margin for mother volume.
+ static final double margin = 1.1;
+
+ // Tolerance factor for moving crystals to appropriate place in mom volume.
+ static final double tolerance = 0.0;
+
+ IIdentifierDictionary dict;
+ IIdentifierHelper helper;
+
+ List<CrystalRange> ranges = new ArrayList<CrystalRange>();
+
+ private boolean checkRange(final int ix, final int iy, final List<CrystalRange> ranges) {
+ if (ranges.size() == 0) {
+ return true;
+ }
+ for (final CrystalRange range : ranges) {
+ if (ix >= range.xIndexMin && ix <= range.xIndexMax && iy >= range.yIndexMin && iy <= range.yIndexMax) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ @Override
+ public void convert(final Subdetector subdet, final Detector detector) {
+
+ LOGGER.info("converting subdetector " + subdet.getName());
+
+ helper = subdet.getDetectorElement().getIdentifierHelper();
+ dict = helper.getIdentifierDictionary();
+
+ // Crystal dimensions.
+ final Element dimensions = subdet.getNode().getChild("dimensions");
+
+ double dx1, dx2, dy1, dy2, dz;
+ Element layout;
+ double beamgap = 0;
+ double beamgapTop, beamgapBottom;
+ int nx, ny;
+ double dface;
+ double tdx, tdy, tdz;
+ double bdx, bdy, bdz;
+ tdx = tdy = tdz = bdx = bdy = bdz = 0.;
+
+ try {
+ dx1 = dimensions.getAttribute("x1").getDoubleValue();
+ dx2 = dimensions.getAttribute("x2").getDoubleValue();
+ dy1 = dimensions.getAttribute("y1").getDoubleValue();
+ dy2 = dimensions.getAttribute("y2").getDoubleValue();
+ dz = dimensions.getAttribute("z").getDoubleValue();
+
+ // Layout parameters.
+ layout = subdet.getNode().getChild("layout");
+ if (layout.getAttribute("beamgap") != null) {
+ beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ } else {
+ if (layout.getAttribute("beamgapTop") == null || layout.getAttribute("beamgapBottom") == null) {
+ throw new RuntimeException(
+ "Missing beamgap parameter in layout element, and beamgapTop or beamgapBottom was not provided.");
+ }
+ }
+ beamgapTop = beamgap;
+ if (layout.getAttribute("beamgapTop") != null) {
+ beamgapTop = layout.getAttribute("beamgapTop").getDoubleValue();
+ }
+ beamgapBottom = beamgap;
+ if (layout.getAttribute("beamgapBottom") != null) {
+ beamgapBottom = layout.getAttribute("beamgapBottom").getDoubleValue();
+ }
+ nx = layout.getAttribute("nx").getIntValue();
+ ny = layout.getAttribute("ny").getIntValue();
+ dface = layout.getAttribute("dface").getDoubleValue();
+
+ final Element topElement = layout.getChild("top");
+ final Element bottomElement = layout.getChild("bottom");
+ if (topElement != null) {
+ if (topElement.getAttribute("dx") != null) {
+ tdx = topElement.getAttribute("dx").getDoubleValue();
+ }
+ if (topElement.getAttribute("dy") != null) {
+ tdy = topElement.getAttribute("dy").getDoubleValue();
+ }
+ if (topElement.getAttribute("dz") != null) {
+ tdz = topElement.getAttribute("dz").getDoubleValue();
+ }
+ }
+ if (bottomElement != null) {
+ if (bottomElement.getAttribute("dx") != null) {
+ bdx = bottomElement.getAttribute("dx").getDoubleValue();
+ }
+ if (bottomElement.getAttribute("dy") != null) {
+ bdy = bottomElement.getAttribute("dy").getDoubleValue();
+ }
+ if (bottomElement.getAttribute("dz") != null) {
+ bdz = bottomElement.getAttribute("dz").getDoubleValue();
+ }
+ }
+ } catch (final DataConversionException e) {
+ throw new RuntimeException("Error converting HPSEcal3 from XML.", e);
+ }
+
+ // Crystal material.
+ final Element mat = subdet.getNode().getChild("material");
+ final String materialName = mat.getAttributeValue("name");
+
+ // Setup range of indices to be skipped.
+ for (final Object obj : layout.getChildren("remove")) {
+ final Element remove = (Element) obj;
+ try {
+ ranges.add(new CrystalRange(remove));
+ } catch (final Exception x) {
+ 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.
+ final Trd crystalTrap = new Trd("crystal_trap", dx1, dx2, dy1, dy2, dz);
+ final ILogicalVolume crystalLogVol = new LogicalVolume("crystal_volume", crystalTrap, MaterialStore
+ .getInstance().get(materialName));
+
+ //
+ // Now we calculate parameters for crystal placement...
+ //
+
+ // Slope of the trapezoid side in X.
+ final double sx = (dx2 - dx1) / (2 * dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in X. Rotation
+ // about Y axis.
+ final double dthetay = atan(sx);
+
+ // Slope of the trapezoid side in Y.
+ final double sy = (dy2 - dy1) / (2 * dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in Y. Rotation
+ // about X axis.
+ final double dthetax = atan(sx);
+
+ // Distance between (virtual) angular origin and center of trapezoid in
+ // X.
+ final double z0x = dx1 / sx + dz;
+
+ // Distance between (virtual) angular origin and center of trapezoid in
+ // Y.
+ final double z0y = dy1 / sy + dz;
+
+ // Odd or even number of crystals in X.
+ final boolean oddx = nx % 2 != 0;
+
+ // Calculate number of X for loop.
+ if (oddx) {
+ nx -= 1;
+ nx /= 2;
+ } else {
+ nx /= 2;
+ }
+
+ double ycorrtot = 0;
+ double zcorrtoty = 0;
+
+ // Crystal sequence number used for unique volume names.
+ int crystaln = 1;
+
+ // Base name for volume.
+ final String baseName = subdet.getName() + "_crystal";
+
+ // World volume.
+ final ILogicalVolume mom = detector.getWorldVolume().getLogicalVolume();
+
+ for (int iy = 1; iy <= ny; iy++) {
+ double zcorrtotx = 0;
+ double xcorrtot = 0;
+
+ final int coeffy = 2 * iy - 1;
+ final double thetax = coeffy * dthetax;
+ final double zcorry = dy1 * (2 * sin(coeffy * dthetax));
+ final double ycorr = zcorry * tan((coeffy - 1) * dthetax);
+ final double ycenter = z0y * sin(coeffy * dthetax) + ycorr + ycorrtot + crystalToleranceY * iy;
+ final double thetaz = 0;
+
+ for (int ix = 0; ix <= nx; ix++) {
+ // Coefficient for even/odd crystal
+ int coeffx = 2 * ix;
+ if (!oddx) {
+ coeffx -= 1;
+ // For even number of crystals, the 0th is skipped.
+ if (ix == 0) {
+ continue;
+ }
+ }
+
+ // Set parameters for next crystal placement.
+ final double thetay = coeffx * dthetay;
+ final double zcorrx = dx1 * (2 * sin(coeffx * dthetay));
+ final double xcorr = zcorrx * tan((coeffx - 1) * dthetay);
+ final double xcenter = z0x * sin(coeffx * dthetay) + xcorr + xcorrtot + crystalToleranceX * ix;
+ double zcenter = z0y * (cos(coeffy * dthetax) - 1) + z0x * (cos(coeffx * dthetay) - 1) + zcorrx
+ + zcorrtotx + zcorry + zcorrtoty;
+ zcenter += dz;
+
+ //
+ // Bottom section.
+ //
+
+ if (this.checkRange(ix, -iy, ranges)) {
+ // Transform of positive bottom crystal.
+ final ITranslation3D iposBot = new Translation3D(xcenter + bdx,
+ -(beamgapBottom + ycenter + tolerance) + bdy, zcenter + tolerance + dface + bdz);
+ final IRotation3D irotBot = new RotationGeant(-thetax, -thetay, thetaz);
+
+ // Place positive crystal.
+ final IPhysicalVolume posCrystalPlacementBot = new PhysicalVolume(
+ new Transform3D(iposBot, irotBot), baseName + crystaln, crystalLogVol, mom, crystaln);
+ this.createDetectorElement(detector, subdet, posCrystalPlacementBot, ix, -iy);
+ ++crystaln;
+ }
+
+ // Reflection to negative.
+ if (ix != 0) {
+ if (this.checkRange(-ix, -iy, ranges)) {
+ // Transform of negative.
+ final ITranslation3D iposnegBot = new Translation3D(-xcenter + bdx,
+ -(beamgapBottom + ycenter + tolerance) + bdy, zcenter + tolerance + dface + bdz);
+ final IRotation3D irotnegBot = new RotationGeant(-thetax, thetay, thetaz);
+
+ // Place negative crystal.
+ final PhysicalVolume negCrystalPlacementBot = new PhysicalVolume(new Transform3D(iposnegBot,
+ irotnegBot), baseName + crystaln, crystalLogVol, detector.getWorldVolume()
+ .getLogicalVolume(), crystaln);
+ this.createDetectorElement(detector, subdet, negCrystalPlacementBot, -ix, -iy);
+ ++crystaln;
+ }
+ }
+
+ if (this.checkRange(ix, iy, ranges)) {
+ // Transform of positive top crystal.
+ final Translation3D iposTop = new Translation3D(xcenter + tdx, beamgapTop + ycenter + tolerance
+ + tdy, zcenter + tolerance + dface + tdz);
+ final IRotation3D irotTop = new RotationGeant(thetax, -thetay, thetaz);
+
+ // Place positive top crystal.
+ final PhysicalVolume posCrystalPlacementTop = new PhysicalVolume(new Transform3D(iposTop, irotTop),
+ baseName + crystaln, crystalLogVol, detector.getWorldVolume().getLogicalVolume(), crystaln);
+ this.createDetectorElement(detector, subdet, posCrystalPlacementTop, ix, iy);
+ ++crystaln;
+ }
+
+ // Reflection to negative.
+ if (ix != 0) {
+ if (this.checkRange(-ix, iy, ranges)) {
+ // Transform of negative.
+ final ITranslation3D iposnegTop = new Translation3D(-xcenter + tdx, beamgapTop + ycenter
+ + tolerance + tdy, zcenter + tolerance + dface + tdz);
+ final IRotation3D irotnegTop = new RotationGeant(thetax, thetay, thetaz);
+
+ // Place negative crystal.
+ final PhysicalVolume negCrystalPlacementTop = new PhysicalVolume(new Transform3D(iposnegTop,
+ irotnegTop), baseName + crystaln, crystalLogVol, detector.getWorldVolume()
+ .getLogicalVolume(), crystaln);
+ this.createDetectorElement(detector, subdet, negCrystalPlacementTop, -ix, iy);
+ ++crystaln;
+ }
+ }
+
+ // Increment running X and Z totals and include tolerance to
+ // avoid overlaps.
+ xcorrtot += xcorr;
+ zcorrtotx += zcorrx;
+ }
+
+ // Increment running Y totals.
+ ycorrtot += ycorr;
+ zcorrtoty += zcorry;
+ }
+
+ // Initialize state of ECal detector element.
+ ((HPSEcalDetectorElement) subdet.getDetectorElement()).initialize();
+ }
+
+ /**
+ * Create a DetectorElement for an ECal crystal.
+ *
+ * @param detector The full detector.
+ * @param subdet The subdetector.
+ * @param crystal The crystal physical volume.
+ * @param ix The value of the ix field.
+ * @param iy The value of the iy field.
+ */
+ private final void createDetectorElement(final Detector detector, final Subdetector subdet,
+ final IPhysicalVolume crystal, final int ix, final int iy) {
+ final String path = "/" + crystal.getName();
+ final IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ expId.setValue(dict.getFieldIndex("system"), subdet.getSystemID());
+ expId.setValue(dict.getFieldIndex("ix"), ix);
+ expId.setValue(dict.getFieldIndex("iy"), iy);
+ final IIdentifier id = helper.pack(expId);
+ new EcalCrystal(subdet.getName() + "_crystal" + crystal.getCopyNumber(), subdet.getDetectorElement(), path, id);
+ }
+
+ @Override
+ public Class getSubdetectorType() {
+ return HPSEcal3.class;
+ }
+
+ @Override
+ public IDetectorElement makeSubdetectorDetectorElement(final Detector detector, final Subdetector subdetector) {
+ LOGGER.info("creating detector element for subdetector " + subdetector.getName());
+ final IDetectorElement subdetectorDE = new HPSEcalDetectorElement(subdetector.getName(),
+ detector.getDetectorElement());
+ subdetector.setDetectorElement(subdetectorDE);
+ return subdetectorDE;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalAPI.java Tue Oct 6 11:36:11 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: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalConverter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalConverter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalConverter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,18 @@
+package org.lcsim.detector.converter.compact;
+
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSEcal;
+
+public class HPSEcalConverter extends AbstractSubdetectorConverter
+{
+ public void convert(Subdetector subdet, Detector detector)
+ {
+ System.out.println(this.getClass().getCanonicalName());
+ }
+
+ public Class getSubdetectorType()
+ {
+ return HPSEcal.class;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSEcalDetectorElement.java Tue Oct 6 11:36:11 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: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterConverter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterConverter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterConverter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,132 @@
+package org.lcsim.detector.converter.compact;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.lcsim.detector.DetectorElement;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IRotation3D;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.LogicalVolume;
+import org.lcsim.detector.PhysicalVolume;
+import org.lcsim.detector.RotationGeant;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.material.MaterialStore;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSMuonCalorimeter;
+
+
+/**
+ * @author jeremym
+ * @version $Id: HPSMuonCalorimeterConverter.java,v 1.2 2013/01/25 00:13:44 jeremy Exp $
+ */
+public class HPSMuonCalorimeterConverter extends AbstractSubdetectorConverter
+{
+
+ public Class getSubdetectorType()
+ {
+ return HPSMuonCalorimeter.class;
+ }
+
+ public void convert(Subdetector subdet, Detector detector)
+ {
+
+ IIdentifierHelper helper = subdet.getDetectorElement().getIdentifierHelper();
+ IIdentifierDictionary dict = helper.getIdentifierDictionary();
+
+ try {
+ Element node = subdet.getNode();
+ String name = node.getAttributeValue("name");
+ ILogicalVolume mother = detector.getWorldVolume().getLogicalVolume();
+
+ for (Object layerObject : node.getChildren("layer")) {
+
+ Element layer = (Element) layerObject;
+ int layerId = layer.getAttribute("id").getIntValue();
+
+ int slice = 1;
+ for (Object boxObject : layer.getChildren("box")) {
+
+ Element element = (Element) boxObject;
+
+ double x, y, z, px, py, pz, rx, ry, rz;
+ x = y = z = px = py = pz = rx = ry = rz = 0.;
+
+ if (element.getAttribute("x") != null) {
+ x = element.getAttribute("x").getDoubleValue();
+ } else {
+ throw new RuntimeException("x is required.");
+ }
+ if (element.getAttribute("y") != null) {
+ y = element.getAttribute("y").getDoubleValue();
+ } else {
+ throw new RuntimeException("y is required.");
+ }
+ if (element.getAttribute("z") != null) {
+ z = element.getAttribute("z").getDoubleValue();
+ } else {
+ throw new RuntimeException("z is required.");
+ }
+
+ if (element.getAttribute("px") != null)
+ px = element.getAttribute("px").getDoubleValue();
+ if (element.getAttribute("py") != null)
+ py = element.getAttribute("py").getDoubleValue();
+ if (element.getAttribute("pz") != null)
+ pz = element.getAttribute("pz").getDoubleValue();
+
+ if (element.getAttribute("rx") != null)
+ rx = element.getAttribute("rx").getDoubleValue();
+ if (element.getAttribute("ry") != null)
+ ry = element.getAttribute("ry").getDoubleValue();
+ if (element.getAttribute("rz") != null)
+ rz = element.getAttribute("rz").getDoubleValue();
+
+ String materialName = element.getAttributeValue("material");
+ IMaterial material = MaterialStore.getInstance().get(materialName);
+
+ String shapeBaseName = name + "_layer" + layerId + "_sublayer" + slice;
+
+ Box box = new Box(shapeBaseName + "_box", x/2, y/2, z/2);
+
+ ITranslation3D pos = new Translation3D(px, py, pz);
+ IRotation3D rot = new RotationGeant(rx, ry, rz);
+ ILogicalVolume vol = new LogicalVolume(shapeBaseName + "_vol", box, material);
+
+ String physVolName = shapeBaseName + "_pv";
+ new PhysicalVolume(new Transform3D(pos, rot), physVolName, vol, mother, 0);
+
+ final IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+ expId.setValue(dict.getFieldIndex("system"), subdet.getSystemID());
+ expId.setValue(dict.getFieldIndex("layer"), layerId);
+ expId.setValue(dict.getFieldIndex("slice"), slice);
+ int side = 1;
+ if (py < 0) {
+ side = -1;
+ }
+ expId.setValue(dict.getFieldIndex("side"), side);
+ final IIdentifier id = helper.pack(expId);
+ new DetectorElement(shapeBaseName, subdet.getDetectorElement(), "/" + physVolName, id);
+
+ ++slice;
+ }
+ }
+ } catch (DataConversionException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public boolean isCalorimeter()
+ {
+ return true;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTracker2Converter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTracker2Converter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTracker2Converter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,407 @@
+package org.lcsim.detector.converter.compact;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.DetectorElement;
+import org.lcsim.detector.DetectorIdentifierHelper;
+import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IRotation3D;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.LogicalVolume;
+import org.lcsim.detector.PhysicalVolume;
+import org.lcsim.detector.RotationGeant;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.converter.compact.subdetector.HpsTracker2;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.material.MaterialStore;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
+import org.lcsim.detector.tracker.silicon.HpsTestRunSiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSTracker2;
+
+/**
+ * Converts an HPSTracker2 XML description into Java runtime objects.
+ * @author Jeremy McCormick <[log in to unmask]>
+ *
+ */
+public class HPSTracker2Converter extends AbstractSubdetectorConverter {
+
+ private Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ private Map<String, LogicalVolume> modules = new HashMap<String, LogicalVolume>();
+ private IMaterial trackingMaterial;
+ private static final boolean debug = false;
+
+ public Class getSubdetectorType() {
+ return HPSTracker2.class;
+ }
+
+ public IIdentifierHelper makeIdentifierHelper(Subdetector subdetector, SystemMap systemMap) {
+ return new SiTrackerIdentifierHelper(subdetector.getDetectorElement(), makeIdentifierDictionary(subdetector), systemMap);
+ }
+
+ public void convert(Subdetector subdet, Detector detector) {
+ trackingMaterial = MaterialStore.getInstance().get("TrackingMaterial");
+ if (trackingMaterial == null) {
+ trackingMaterial = MaterialStore.getInstance().get("Air");
+ }
+
+ // Get the tracking volume for module placement.
+ ILogicalVolume trackingVolume = detector.getTrackingVolume().getLogicalVolume();
+
+ // Get ID helper and dictionary for subdetector.
+ DetectorIdentifierHelper helper = (DetectorIdentifierHelper) subdet.getDetectorElement().getIdentifierHelper();
+ IIdentifierDictionary iddict = subdet.getDetectorElement().getIdentifierHelper().getIdentifierDictionary();
+ int nfields = helper.getIdentifierDictionary().getNumberOfFields();
+
+ // Get XML node for this subdetector.
+ Element node = subdet.getNode();
+
+ // Create the module logical volumes.
+ for (Iterator i = node.getChildren("module").iterator(); i.hasNext();) {
+ Element module = (Element) i.next();
+ String moduleName = module.getAttributeValue("name");
+ moduleParameters.put(moduleName, new ModuleParameters(module));
+ modules.put(moduleName, makeModule(moduleParameters.get(moduleName)));
+ }
+
+ try {
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();) {
+
+ Element layerElement = (Element) i.next();
+ int layerId = -1;
+ layerId = layerElement.getAttribute("id").getIntValue();
+
+ // Layer identifier.
+ IExpandedIdentifier layerPosId = new ExpandedIdentifier(nfields);
+ layerPosId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ layerPosId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ layerPosId.setValue(helper.getFieldIndex("layer"), layerId);
+
+ // DetectorElement for layer.
+ IDetectorElement layerDe = new DetectorElement(subdet.getName() + "_layer" + layerId, subdet.getDetectorElement(), helper.pack(layerPosId));
+
+ // Loop over modules within layer.
+ for (Iterator j = layerElement.getChildren("module_placement").iterator(); j.hasNext();) {
+
+ Element modulePlacementElement = (Element)j.next();
+ String moduleName = modulePlacementElement.getAttributeValue("name");
+ int moduleNumber = modulePlacementElement.getAttribute("id").getIntValue();
+
+ // Get the position and rotation parameters. All must be explicitly specified.
+ double x, y, z;
+ double rx, ry, rz;
+ x = modulePlacementElement.getAttribute("x").getDoubleValue();
+ y = modulePlacementElement.getAttribute("y").getDoubleValue();
+ z = modulePlacementElement.getAttribute("z").getDoubleValue();
+ rx = modulePlacementElement.getAttribute("rx").getDoubleValue();
+ ry = modulePlacementElement.getAttribute("ry").getDoubleValue();
+ rz = modulePlacementElement.getAttribute("rz").getDoubleValue();
+
+ ITranslation3D pos = new Translation3D(x, y, z);
+ IRotation3D rot = new RotationGeant(rx, ry, rz);
+
+ String modulePlacementName = subdet.getName() + "_" + moduleName + "_layer" + layerId + "_module" + moduleNumber;
+
+ LogicalVolume lv = modules.get(moduleName);
+ IPhysicalVolume modulePhysVol = new PhysicalVolume(new Transform3D(pos,rot), modulePlacementName, lv, trackingVolume, 0);
+
+ if (debug)
+ System.out.println("made module: " + modulePhysVol.getName());
+
+ // Module DetectorElement.
+ String modulePath = "/" + detector.getTrackingVolume().getName() + "/" + modulePlacementName;
+ SiTrackerModule moduleDe = new SiTrackerModule(modulePlacementName, layerDe, modulePath, moduleNumber);
+
+ if (debug)
+ System.out.println("created new SiTrackerModule called " + modulePlacementName + " with path: " + modulePath);
+
+ // Make SiSensor DetectorElements.
+ int sensorNumber = 0;
+ for (IPhysicalVolume componentPhysVol : modulePhysVol.getLogicalVolume().getDaughters()) {
+ // Setup the sensor.
+ if (componentPhysVol.getLogicalVolume().getDaughters().size() != 0) {
+
+ // Sensor physical volume.
+ IPhysicalVolume sensorPhysVol = componentPhysVol.getLogicalVolume().getDaughters().get(0);
+
+ ExpandedIdentifier expId = new ExpandedIdentifier(iddict.getNumberOfFields());
+
+ // Setup SiSensor's identifier.
+ expId.setValue(iddict.getFieldIndex("system"), subdet.getSystemID());
+ expId.setValue(iddict.getFieldIndex("barrel"), 0);
+ expId.setValue(iddict.getFieldIndex("layer"), helper.getValue(layerDe.getIdentifier(), "layer"));
+ expId.setValue(iddict.getFieldIndex("module"), ((SiTrackerModule) moduleDe).getModuleId());
+ expId.setValue(iddict.getFieldIndex("sensor"), sensorNumber);
+
+ // Packed identifier.
+ IIdentifier sensorId = iddict.pack(expId);
+
+ // Sensor paths.
+ String sensorPath = modulePath.toString() + "/" + componentPhysVol.getName() + "/" + sensorPhysVol.getName();
+ String sensorName = moduleDe.getName() + "_sensor" + sensorNumber;
+
+ // Create the sensor.
+ HpsSiSensor sensor = null;
+ if(moduleParameters.get(moduleName).getType().equals(HpsTestRunSiSensor.class.getSimpleName())){
+ sensor = new HpsTestRunSiSensor(sensorNumber, sensorName, moduleDe, sensorPath, sensorId);
+ } else {
+ sensor = new HpsSiSensor(sensorNumber, sensorName, moduleDe, sensorPath, sensorId);
+ }
+
+ if (debug)
+ System.out.println("created sensor " + sensor.getName());
+
+ // Increment sensor numbering.
+ ++sensorNumber;
+ }
+ }
+ }
+ }
+ }
+ catch (DataConversionException e) {
+ throw new RuntimeException(e);
+ }
+
+ // Create the stereo layers
+ ((HpsTracker2) subdet.getDetectorElement()).createStereoLayers();
+ }
+
+ private LogicalVolume makeModule(ModuleParameters params)
+ {
+ double thickness = params.getThickness();
+ double x, y;
+ y = params.getDimension(0); // Y is long dimension along world's X axis.
+ x = params.getDimension(1); // X is short dimension along world Y axis.
+
+ Box box = new Box(params.getName() + "Box", x / 2, y / 2, thickness / 2);
+ LogicalVolume volume = new LogicalVolume(params.getName() + "Volume", box, trackingMaterial);
+
+ makeModuleComponents(volume, params);
+
+ return volume;
+ }
+
+ private void makeModuleComponents(LogicalVolume moduleVolume, ModuleParameters moduleParameters)
+ {
+ double moduleY = moduleParameters.getDimension(0);
+ double moduleX = moduleParameters.getDimension(1);
+ Box box = (Box)moduleVolume.getSolid();
+ double moduleZ = box.getZHalfLength() * 2;
+ double posZ = -moduleZ / 2;
+ String moduleName = moduleVolume.getName();
+ int sensorNumber = 0;
+ for (ModuleComponentParameters component : moduleParameters)
+ {
+ double componentThickness = component.getThickness();
+ IMaterial material = MaterialStore.getInstance().get(component.getMaterialName());
+ if (material == null)
+ {
+ throw new RuntimeException("The material " + component.getMaterialName() + " does not exist in the materials database.");
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+ posZ += componentThickness / 2;
+ String componentName = moduleName + "_component" + componentNumber;
+ Box componentBox = new Box(componentName + "Box", moduleX / 2, moduleY / 2, componentThickness / 2);
+ LogicalVolume componentVolume = new LogicalVolume(componentName, componentBox, material);
+ double zrot = 0;
+ if (sensitive)
+ {
+ if (sensorNumber > 1)
+ {
+ throw new RuntimeException("Exceeded maximum of 2 sensors per module.");
+ }
+ // Flip 180 deg for 1st sensor.
+ if (sensorNumber == 0)
+ {
+ zrot = Math.PI;
+ }
+ String sensorName = componentName + "Sensor" + sensorNumber;
+ double sensorX = component.getDimensionY(); // Flipped so X is actually Y.
+ double sensorY = component.getDimensionX(); // Flipped so Y is actually X.
+ Box sensorBox = new Box(sensorName + "Box", sensorX / 2, sensorY / 2, componentThickness / 2);
+ LogicalVolume sensorVol = new LogicalVolume(sensorName, sensorBox, material);
+ Translation3D sensorPosition = new Translation3D(0, 0, 0);
+ RotationGeant sensorRotation = new RotationGeant(0, 0, zrot);
+ new PhysicalVolume(new Transform3D(sensorPosition, sensorRotation), sensorName, sensorVol, componentVolume, sensorNumber);
+ ++sensorNumber;
+ }
+ Translation3D position = new Translation3D(0., 0., posZ);
+ RotationGeant rotation = new RotationGeant(0, 0, zrot);
+ PhysicalVolume pv = new PhysicalVolume(new Transform3D(position, rotation), componentName, componentVolume, moduleVolume, componentNumber);
+ pv.setSensitive(sensitive);
+ posZ += componentThickness / 2;
+ }
+ }
+
+ private static class ModuleComponentParameters {
+ private String materialName;
+ private double thickness;
+ private boolean sensitive;
+ private int componentNumber;
+ private String vis;
+ private double dimX, dimY;
+
+ ModuleComponentParameters(double dimX, double dimY, double thickness, String materialName, int componentNumber, boolean sensitive, String vis) {
+ this.dimX = dimX;
+ this.dimY = dimY;
+ this.thickness = thickness;
+ this.materialName = materialName;
+ this.sensitive = sensitive;
+ this.componentNumber = componentNumber;
+ this.vis = vis;
+ }
+
+ double getThickness() {
+ return thickness;
+ }
+
+ double getDimensionX() {
+ return dimX;
+ }
+
+ double getDimensionY() {
+ return dimY;
+ }
+
+ String getMaterialName() {
+ return materialName;
+ }
+
+ boolean isSensitive() {
+ return sensitive;
+ }
+
+ int getComponentNumber() {
+ return componentNumber;
+ }
+
+ String getVis() {
+ return vis;
+ }
+ }
+
+ private static class ModuleParameters extends ArrayList<ModuleComponentParameters> {
+ private double thickness;
+ private String name;
+ private double dimensions[] = new double[3];
+ private String vis;
+ private String type = "";
+
+ ModuleParameters(Element element) {
+ name = element.getAttributeValue("name");
+
+ if (element.getAttribute("vis") != null)
+ this.vis = element.getAttribute("vis").getValue();
+
+ if(element.getAttribute("type") != null)
+ this.type = element.getAttributeValue("type");
+
+ // Optional dimension parameters (not always present).
+ if (element.getChild("trd") != null) {
+ Element trd = element.getChild("trd");
+ try {
+ dimensions[0] = trd.getAttribute("x1").getDoubleValue();
+ dimensions[1] = trd.getAttribute("x2").getDoubleValue();
+ dimensions[2] = trd.getAttribute("z").getDoubleValue();
+ } catch (DataConversionException x) {
+ throw new RuntimeException(x);
+ }
+ } else if (element.getChild("box") != null) {
+ Element box = element.getChild("box");
+ try {
+ dimensions[0] = box.getAttribute("x").getDoubleValue();
+ dimensions[1] = box.getAttribute("y").getDoubleValue();
+ } catch (DataConversionException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ int cntr = 0;
+ for (Object o : element.getChildren("module_component")) {
+ try {
+
+ Element e = (Element) o;
+
+ double thickness = e.getAttribute("thickness").getDoubleValue();
+
+ String materialName = e.getAttributeValue("material");
+
+ boolean sensitive = false;
+ if (e.getAttribute("sensitive") != null)
+ sensitive = e.getAttribute("sensitive").getBooleanValue();
+ String componentVis = null;
+ if (e.getAttribute("vis") != null)
+ componentVis = e.getAttribute("vis").getValue();
+
+ // Sensors may have reduced dimensions for dead area.
+ double x = dimensions[0]; // default
+ double y = dimensions[1]; // default
+ if (sensitive && e.getChild("dimensions") != null) {
+ Element dimensions = e.getChild("dimensions");
+ x = dimensions.getAttribute("x").getDoubleValue();
+ y = dimensions.getAttribute("y").getDoubleValue();
+ }
+ add(new ModuleComponentParameters(x, y, thickness, materialName, cntr, sensitive, componentVis));
+ } catch (JDOMException x) {
+ throw new RuntimeException(x);
+ }
+ ++cntr;
+ }
+ calculateThickness();
+ }
+
+ void calculateThickness() {
+ thickness = 0.; // reset thickness
+ for (ModuleComponentParameters p : this) {
+ thickness += p.getThickness();
+ }
+ }
+
+ double getThickness() {
+ return thickness;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ double getDimension(int i) {
+ if (i > (dimensions.length - 1) || i < 0)
+ throw new RuntimeException("Invalid dimensions index: " + i);
+ return dimensions[i];
+ }
+
+ String getType() {
+ return type;
+ }
+ }
+
+ public IDetectorElement makeSubdetectorDetectorElement(Detector detector, Subdetector subdetector)
+ {
+ IDetectorElement subdetectorDE =
+ new HpsTracker2(subdetector.getName(), detector.getDetectorElement());
+ subdetector.setDetectorElement(subdetectorDE);
+ return subdetectorDE;
+ }
+
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTrackerConverter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTrackerConverter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/converter/compact/HPSTrackerConverter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,584 @@
+package org.lcsim.detector.converter.compact;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.DetectorElement;
+import org.lcsim.detector.DetectorIdentifierHelper;
+import org.lcsim.detector.DetectorIdentifierHelper.SystemMap;
+import org.lcsim.detector.IDetectorElement;
+
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IPhysicalVolumePath;
+import org.lcsim.detector.IRotation3D;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.LogicalVolume;
+import org.lcsim.detector.PhysicalVolume;
+import org.lcsim.detector.RotationGeant;
+import org.lcsim.detector.RotationPassiveXYZ;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.material.MaterialStore;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.geometry.compact.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.HPSTracker;
+
+public class HPSTrackerConverter extends AbstractSubdetectorConverter
+{
+ Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ Map<String, LogicalVolume> modules = new HashMap<String, LogicalVolume>();
+ IMaterial vacuum;
+
+ public Class getSubdetectorType()
+ {
+ return HPSTracker.class;
+ }
+
+ public IIdentifierHelper makeIdentifierHelper(Subdetector subdetector, SystemMap systemMap)
+ {
+ return new SiTrackerIdentifierHelper(subdetector.getDetectorElement(), makeIdentifierDictionary(subdetector), systemMap);
+ }
+
+ public void convert(Subdetector subdet, Detector detector)
+ {
+ try
+ {
+ Element node = subdet.getNode();
+ String subdetName = node.getAttributeValue("name");
+ vacuum = MaterialStore.getInstance().get("Air");
+
+ boolean reflect = true;
+ if (node.getAttribute("reflect") != null)
+ {
+ reflect = node.getAttribute("reflect").getBooleanValue();
+ }
+
+
+
+ IDetectorElement subdetDetElem = subdet.getDetectorElement();
+ DetectorIdentifierHelper helper = (DetectorIdentifierHelper) subdetDetElem.getIdentifierHelper();
+ int nfields = helper.getIdentifierDictionary().getNumberOfFields();
+ IDetectorElement endcapPos = null;
+ IDetectorElement endcapNeg = null;
+ try
+ {
+ // Positive endcap DE
+ IExpandedIdentifier endcapPosId = new ExpandedIdentifier(nfields);
+ endcapPosId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ endcapPosId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ endcapPos = new DetectorElement(subdet.getName() + "_positive", subdetDetElem);
+ endcapPos.setIdentifier(helper.pack(endcapPosId));
+ if (reflect)
+ {
+ IExpandedIdentifier endcapNegId = new ExpandedIdentifier(nfields);
+ endcapNegId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ endcapNegId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ endcapNeg = new DetectorElement(subdet.getName() + "_negative", subdetDetElem);
+ endcapNeg.setIdentifier(helper.pack(endcapNegId));
+ }
+ }
+ catch (Exception x)
+ {
+ throw new RuntimeException(x);
+ }
+
+ for (Iterator i = node.getChildren("module").iterator(); i.hasNext();)
+ {
+ Element module = (Element) i.next();
+ String moduleName = module.getAttributeValue("name");
+ moduleParameters.put(moduleName, new ModuleParameters(module));
+ modules.put(moduleName, makeModule(moduleParameters.get(moduleName)));
+ }
+
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
+ {
+ Element layerElement = (Element) i.next();
+
+ int layerId = layerElement.getAttribute("id").getIntValue();
+
+ // Positive endcap layer.
+ IExpandedIdentifier layerPosId = new ExpandedIdentifier(nfields);
+ layerPosId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ layerPosId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ layerPosId.setValue(helper.getFieldIndex("layer"), layerId);
+ IDetectorElement layerPos = new DetectorElement(endcapPos.getName() + "_layer" + layerId, endcapPos, helper.pack(layerPosId));
+
+ // Negative endcap layer.
+ IDetectorElement layerNeg = null;
+ if (reflect)
+ {
+ IExpandedIdentifier layerNegId = new ExpandedIdentifier(nfields);
+ layerNegId.setValue(helper.getFieldIndex("system"), subdet.getSystemID());
+ layerNegId.setValue(helper.getFieldIndex("barrel"), helper.getBarrelValue());
+ layerNegId.setValue(helper.getFieldIndex("layer"), layerId);
+ layerNeg = new DetectorElement(endcapNeg.getName() + "_layer_reflected" + layerId, endcapNeg, helper.pack(layerNegId));
+ }
+
+ int moduleNumber = 0;
+ for (Iterator j = layerElement.getChildren("quadrant").iterator(); j.hasNext();)
+ {
+ Element ringElement = (Element) j.next();
+ double zLayer = ringElement.getAttribute("z").getDoubleValue();
+ double dz = ringElement.getAttribute("dz").getDoubleValue();
+ double xStart = ringElement.getAttribute("xStart").getDoubleValue();
+ double xStep = ringElement.getAttribute("xStep").getDoubleValue();
+ int nx = ringElement.getAttribute("nx").getIntValue();
+ double yStart = ringElement.getAttribute("yStart").getDoubleValue();
+ int ny = ringElement.getAttribute("ny").getIntValue();
+ double yStep = ringElement.getAttribute("yStep").getDoubleValue();
+
+ double top_phi0 = 0;
+ if (ringElement.getAttribute("top_phi0") != null)
+ {
+ top_phi0 = ringElement.getAttribute("top_phi0").getDoubleValue();
+ }
+ double bot_phi0 = 0;
+ if (ringElement.getAttribute("bot_phi0") != null)
+ {
+ bot_phi0 = ringElement.getAttribute("bot_phi0").getDoubleValue();
+ }
+ String module = ringElement.getAttributeValue("module");
+ LogicalVolume moduleVolume = modules.get(module);
+ if (moduleVolume == null)
+ {
+ throw new RuntimeException("Module " + module + " was not found.");
+ }
+ double theta = 0;
+ if (ringElement.getAttribute("theta") != null)
+ {
+ theta = ringElement.getAttribute("theta").getDoubleValue();
+ }
+
+ ModuleParameters modPars = moduleParameters.get(module);
+
+ double x, y, z;
+ z = zLayer;
+ x = xStart;
+ // System.out.println("Making modules...nx=" + nx + ";ny=" + ny);
+ for (int k = 0; k < nx; k++ )
+ {
+ y = yStart;
+ for (int kk = 0; kk < ny; kk++ )
+ {
+ String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
+ Translation3D p = new Translation3D(x, y, z + dz);
+ //RotationGeant rot = new RotationGeant(0, theta,-(Math.PI / 2 + top_phi0));
+ RotationGeant rot = new RotationGeant(0, theta,-Math.PI/2 - top_phi0);
+ new PhysicalVolume(new Transform3D(p, rot), moduleBaseName, moduleVolume, detector.getTrackingVolume().getLogicalVolume(), 0);
+ String path = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName;
+ new SiTrackerModule(moduleBaseName, layerPos, path, moduleNumber);
+ ++moduleNumber;
+ if (reflect)
+ {
+ Translation3D pr = new Translation3D(x, -y, z + dz);
+ //first x, then y, then z...
+ //RotationGeant rotr = new RotationGeant(0, theta, Math.PI/2 - bot_phi0);
+ RotationGeant rotr = new RotationGeant(0, theta, -Math.PI/2 - bot_phi0);
+ String path2 = "/" + detector.getTrackingVolume().getName() + "/" + moduleBaseName + "_reflected";
+ new PhysicalVolume(new Transform3D(pr, rotr), moduleBaseName + "_reflected", moduleVolume, detector.getTrackingVolume().getLogicalVolume(), k);
+ new SiTrackerModule(moduleBaseName + "_reflected", layerNeg, path2, moduleNumber);
+ }
+
+ dz = -dz;
+ y += yStep;
+ ++moduleNumber;
+ }
+ x += xStep;
+ }
+ }
+ }
+ }
+ catch (JDOMException except)
+ {
+ throw new RuntimeException(except);
+ }
+ makeSensors(subdet);
+ }
+
+ private LogicalVolume makeModule(ModuleParameters params)
+ {
+ double thickness = params.getThickness();
+ double x, y;
+ //x = params.getDimension(0);
+ //y = params.getDimension(1);
+ y = params.getDimension(0); // Y is long dimension along world's X axis.
+ x = params.getDimension(1); // X is short dimension along world Y axis.
+
+ Box box = new Box(params.getName() + "Box", x / 2, y / 2, thickness / 2);
+ LogicalVolume volume = new LogicalVolume(params.getName() + "Volume", box, vacuum);
+
+ makeModuleComponents(volume, params);
+
+ return volume;
+ }
+
+ private void makeModuleComponents(LogicalVolume moduleVolume, ModuleParameters moduleParameters)
+ {
+ //double moduleX = moduleParameters.getDimension(0);
+ //double moduleY = moduleParameters.getDimension(1);
+ double moduleY = moduleParameters.getDimension(0);
+ double moduleX = moduleParameters.getDimension(1);
+ Box box = (Box)moduleVolume.getSolid();
+ double moduleZ = box.getZHalfLength() * 2;
+ double posZ = -moduleZ / 2;
+ String moduleName = moduleVolume.getName();
+ int sensorNumber = 0;
+ for (ModuleComponentParameters component : moduleParameters)
+ {
+ double componentThickness = component.getThickness();
+ IMaterial material = MaterialStore.getInstance().get(component.getMaterialName());
+ if (material == null)
+ {
+ throw new RuntimeException("The material " + component.getMaterialName() + " does not exist in the materials database.");
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+ posZ += componentThickness / 2;
+ String componentName = moduleName + "_component" + componentNumber;
+ Box componentBox = new Box(componentName + "Box", moduleX / 2, moduleY / 2, componentThickness / 2);
+ LogicalVolume componentVolume = new LogicalVolume(componentName, componentBox, material);
+ double zrot = 0;
+ if (sensitive)
+ {
+ if (sensorNumber > 1)
+ {
+ throw new RuntimeException("Exceeded maximum of 2 sensors per module.");
+ }
+ // Flip 180 deg for 1st sensor.
+ if (sensorNumber == 0)
+ {
+ zrot = Math.PI;
+ }
+ String sensorName = componentName + "Sensor" + sensorNumber;
+ double sensorX = component.getDimensionY(); // Flipped so X is actually Y.
+ //if (sensorX > moduleX)
+ // throw new RuntimeException("Sensor X dimension " + sensorX + " is too big for module.");
+ double sensorY = component.getDimensionX(); // Flipped so Y is actually X.
+ //if (sensorY > moduleY)
+ // throw new RuntimeException("Sensor Y dimension " + sensorY + " is too big for module.");
+ Box sensorBox = new Box(sensorName + "Box", sensorX / 2, sensorY / 2, componentThickness / 2);
+ LogicalVolume sensorVol = new LogicalVolume(sensorName, sensorBox, material);
+ Translation3D sensorPosition = new Translation3D(0, 0, 0);
+ RotationGeant sensorRotation = new RotationGeant(0, 0, zrot);
+ //PhysicalVolume sensorPhysVol =
+ new PhysicalVolume(new Transform3D(sensorPosition, sensorRotation), sensorName, sensorVol, componentVolume, sensorNumber);
+ // TODO Could make sensors here?
+ ++sensorNumber;
+ }
+ Translation3D position = new Translation3D(0., 0., posZ);
+ RotationGeant rotation = new RotationGeant(0, 0, zrot);
+ PhysicalVolume pv = new PhysicalVolume(new Transform3D(position, rotation), componentName, componentVolume, moduleVolume, componentNumber);
+ pv.setSensitive(sensitive);
+ posZ += componentThickness / 2;
+ }
+ }
+
+ // Called after geometry is in place to create the Sensor DetectorElements.
+ private void makeSensors(Subdetector subdet)
+ {
+ SiTrackerIdentifierHelper helper = (SiTrackerIdentifierHelper) subdet.getDetectorElement().getIdentifierHelper();
+ for (IDetectorElement endcap : subdet.getDetectorElement().getChildren())
+ {
+ for (IDetectorElement layer : endcap.getChildren())
+ {
+ for (IDetectorElement module : layer.getChildren())
+ {
+ IPhysicalVolume modulePhysVol = module.getGeometry().getPhysicalVolume();
+ IPhysicalVolumePath modulePath = module.getGeometry().getPath();
+ int sensorId = 0;
+ for (IPhysicalVolume componentPhysVol : modulePhysVol.getLogicalVolume().getDaughters())
+ {
+ // Setup the sensor.
+ if (componentPhysVol.getLogicalVolume().getDaughters().size() != 0)
+ {
+ IPhysicalVolume sensorPhysVol = componentPhysVol.getLogicalVolume().getDaughters().get(0);
+
+ IIdentifierDictionary iddict = subdet.getDetectorElement().getIdentifierHelper().getIdentifierDictionary();
+
+ ExpandedIdentifier expId = new ExpandedIdentifier(iddict.getNumberOfFields());
+ expId.setValue(iddict.getFieldIndex("system"), subdet.getSystemID());
+
+ if (helper.isEndcapPositive(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getEndcapPositiveValue());
+ }
+ else if (helper.isEndcapNegative(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getEndcapNegativeValue());
+ }
+ else if (helper.isBarrel(endcap.getIdentifier()))
+ {
+ expId.setValue(iddict.getFieldIndex("barrel"), helper.getBarrelValue());
+ }
+ else
+ {
+ throw new RuntimeException(endcap.getName() + " is not a positive or negative endcap!");
+ }
+ expId.setValue(iddict.getFieldIndex("layer"), layer.getIdentifierHelper().getValue(layer.getIdentifier(), "layer"));
+ expId.setValue(iddict.getFieldIndex("module"), ((SiTrackerModule) module).getModuleId());
+ expId.setValue(iddict.getFieldIndex("sensor"), sensorId);
+
+ IIdentifier id = iddict.pack(expId);
+
+ String sensorPath = modulePath.toString() + "/" + componentPhysVol.getName() + "/" + sensorPhysVol.getName();
+ String sensorName = module.getName() + "_sensor" + sensorId;
+
+ // Create the sensor.
+ SiSensor sensor = new SiSensor(sensorId, sensorName, module, sensorPath, id);
+
+ // Configure parameters of strips, etc.
+ //configSensor(sensor);
+
+ // Increment sensor numbering.
+ ++sensorId;
+ }
+ // }
+ }
+ }
+ }
+ }
+ }
+
+ // Parameters...
+ private double readoutCapacitanceIntercept = 0;
+ private double readoutCapacitanceSlope = 0.16;
+ private double senseCapacitanceIntercept = 0;
+ private double senseCapacitanceSlope = 0.16;
+ private double readoutStripPitch = 0.060;
+ private double senseStripPitch = 0.030;
+ private double readoutTransferEfficiency = 0.986;
+ private double senseTransferEfficiency = 0.419;
+
+ // TODO: Move this method to a Driver class.
+ /*
+ private void configSensor(SiSensor sensor)
+ {
+ //
+ Box sensorSolid = (Box) sensor.getGeometry().getLogicalVolume().getSolid();
+
+ Polygon3D pside = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, 1)).get(0);
+ Polygon3D nside = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, -1)).get(0);
+
+ sensor.setBiasSurface(ChargeCarrier.HOLE, pside); // P side collects holes.
+ sensor.setBiasSurface(ChargeCarrier.ELECTRON, nside); // N side collects electrons.
+
+ // Setup electrodes on the XY front and back surfaces of the Box.
+ ITranslation3D electrodesPosition = new Translation3D(VecOp.mult(-pside.getDistance(), pside.getNormal())); // Translate to outside of polygon (always the same).
+
+ // Strip angle.
+ IRotation3D electrodesRotation = new RotationPassiveXYZ(0.0, 0.0, 0.0); // Strips aligned to edge of sensor, ALWAYS.
+ Transform3D electrodesTransform = new Transform3D(electrodesPosition, electrodesRotation);
+
+ // Free calculation of readout electrodes, sense electrodes determined thereon.
+ SiStrips readoutElectrodes = new SiStrips(ChargeCarrier.HOLE, readoutStripPitch, sensor, electrodesTransform);
+ SiStrips senseElectrodes = new SiStrips(ChargeCarrier.HOLE, senseStripPitch, (readoutElectrodes.getNCells()*2-1), sensor, electrodesTransform);
+ //
+
+ // Readout electrode parameters.
+ readoutElectrodes.setCapacitanceIntercept(readoutCapacitanceIntercept);
+ readoutElectrodes.setCapacitanceSlope(readoutCapacitanceSlope);
+
+ // Sense electrode parameters.
+ senseElectrodes.setCapacitanceIntercept(senseCapacitanceIntercept);
+ senseElectrodes.setCapacitanceSlope(senseCapacitanceSlope);
+
+ // Set sense and readout electrodes.
+ sensor.setSenseElectrodes(senseElectrodes);
+ sensor.setReadoutElectrodes(readoutElectrodes);
+
+ // Charge transfer efficiency.
+ double[][] transferEfficiencies = {{readoutTransferEfficiency, senseTransferEfficiency}};
+ sensor.setTransferEfficiencies(ChargeCarrier.HOLE, new BasicMatrix(transferEfficiencies));
+ }
+ */
+
+ static class ModuleComponentParameters
+ {
+ protected String materialName;
+ protected double thickness;
+ protected boolean sensitive;
+ protected int componentNumber;
+ protected String vis;
+ protected double dimX, dimY;
+
+ public ModuleComponentParameters(double dimX, double dimY, double thickness, String materialName, int componentNumber, boolean sensitive, String vis)
+ {
+ this.dimX = dimX;
+ this.dimY = dimY;
+ this.thickness = thickness;
+ this.materialName = materialName;
+ this.sensitive = sensitive;
+ this.componentNumber = componentNumber;
+ this.vis = vis;
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public double getDimensionX()
+ {
+ return dimX;
+ }
+
+ public double getDimensionY()
+ {
+ return dimY;
+ }
+
+ public String getMaterialName()
+ {
+ return materialName;
+ }
+
+ public boolean isSensitive()
+ {
+ return sensitive;
+ }
+
+ public int getComponentNumber()
+ {
+ return componentNumber;
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+
+ static class ModuleParameters extends ArrayList<ModuleComponentParameters>
+ {
+ double thickness;
+ String name;
+ double dimensions[] = new double[3];
+ String vis;
+
+ public ModuleParameters(Element element)
+ {
+ name = element.getAttributeValue("name");
+ if (element.getAttribute("vis") != null)
+ this.vis = element.getAttribute("vis").getValue();
+ // Optional dimension parameters (not always present).
+ if (element.getChild("trd") != null)
+ {
+ Element trd = element.getChild("trd");
+ try
+ {
+ dimensions[0] = trd.getAttribute("x1").getDoubleValue();
+ dimensions[1] = trd.getAttribute("x2").getDoubleValue();
+ dimensions[2] = trd.getAttribute("z").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+ else if (element.getChild("box") != null)
+ {
+ Element box = element.getChild("box");
+ try
+ {
+ dimensions[0] = box.getAttribute("x").getDoubleValue();
+ dimensions[1] = box.getAttribute("y").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+ int cntr = 0;
+ for (Object o : element.getChildren("module_component"))
+ {
+ try
+ {
+
+ Element e = (Element) o;
+
+ double thickness = e.getAttribute("thickness").getDoubleValue();
+
+ String materialName = e.getAttributeValue("material");
+
+ boolean sensitive = false;
+ if (e.getAttribute("sensitive") != null)
+ sensitive = e.getAttribute("sensitive").getBooleanValue();
+ String componentVis = null;
+ if (e.getAttribute("vis") != null)
+ componentVis = e.getAttribute("vis").getValue();
+
+ // Sensors may have reduced dimensions for dead area.
+ double x = dimensions[0]; // default
+ double y = dimensions[1]; // default
+ if (sensitive && e.getChild("dimensions") != null)
+ {
+ Element dimensions = e.getChild("dimensions");
+ x = dimensions.getAttribute("x").getDoubleValue();
+ y = dimensions.getAttribute("y").getDoubleValue();
+ // System.out.println("x,y="+x+","+y);
+ }
+ add(new ModuleComponentParameters(x, y, thickness, materialName, cntr, sensitive, componentVis));
+ }
+ catch (JDOMException x)
+ {
+ throw new RuntimeException(x);
+ }
+ ++cntr;
+ }
+ calculateThickness();
+ }
+
+ public void calculateThickness()
+ {
+ thickness = 0.; // reset thickness
+ for (ModuleComponentParameters p : this)
+ {
+ thickness += p.getThickness();
+ }
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public double getDimension(int i)
+ {
+ if (i > (dimensions.length - 1) || i < 0)
+ throw new RuntimeException("Invalid dimensions index: " + i);
+ return dimensions[i];
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/silicon/HpsTestRunSiSensor.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/silicon/HpsTestRunSiSensor.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/detector/tracker/silicon/HpsTestRunSiSensor.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,98 @@
+package org.lcsim.detector.tracker.silicon;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.identifier.IIdentifier;
+
+
+/**
+ * This class extends {@link HpsSiSensor} with conditions specific to HPS SVT half-modules
+ * (sensors) used during the test run. Each half-module is uniquely identified by
+ * an FPGA/Hybrid ID pair which is then related to calibration conditions such as
+ * baseline, noise gain etc.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Omar Moreno <[log in to unmask]>
+ */
+public class HpsTestRunSiSensor extends HpsSiSensor {
+
+
+ protected int fpgaID;
+ protected int hybridID;
+
+
+ /**
+ * This class constructor matches the signature of <code>SiSensor</code>.
+ * @param sensorid The sensor ID.
+ * @param name The name of the sensor.
+ * @param parent The parent DetectorElement.
+ * @param support The physical support path.
+ * @param id The identifier of the sensor.
+ */
+ public HpsTestRunSiSensor(
+ int sensorid,
+ String name,
+ IDetectorElement parent,
+ String support,
+ IIdentifier id)
+ {
+ super(sensorid, name, parent, support, id);
+ }
+
+
+
+ /**
+ * Get the FPGA ID associated with this sensor.
+ *
+ * @return The FPGA ID
+ */
+ public int getFpgaID() {
+ return fpgaID;
+ }
+
+ /**
+ * Get the hybrid ID associated with this sensor.
+ *
+ * @return The hybrid ID
+ */
+ public int getHybridID() {
+ return hybridID;
+ }
+
+ @Override
+ public int getFebID(){
+ throw new RuntimeException("This method is not supported for the HpsTestRunSiSensor.");
+ }
+
+ @Override
+ public int getFebHybridID(){
+ throw new RuntimeException("This method is not supported for the HpsTestRunSiSensor.");
+ }
+
+ /**
+ * Set the FPGA ID associated with this sensor.
+ *
+ * @param The FPGA ID
+ */
+ public void setFpgaID(int fpgaID) {
+ this.fpgaID = fpgaID;
+ }
+
+ /**
+ * Set the hybrid ID associated with this sensor.
+ *
+ * @param The hybrid ID.
+ */
+ public void setHybridID(int hybridID) {
+ this.hybridID = hybridID;
+ }
+
+ @Override
+ public void setFebID(int febID) {
+ throw new RuntimeException("This method is not supported for the HpsTestRunSiSensor.");
+ }
+
+ @Override
+ public void setFebHybridID(int febHybridID) {
+ throw new RuntimeException("This method is not supported for the HpsTestRunSiSensor.");
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,258 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import static java.lang.Math.atan;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import static java.lang.Math.tan;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.Define;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * LCDD model for the HPS inner ECal.
+ *
+ * Coordinate System Notes:
+ *
+ * Beam travels in +X direction.
+ * Magnetic field is -Z (????).
+ * Y is the beam bend plane.
+ *
+ * The dimensions element defines the crystal HALF dimensions: x1, x2, y1, y2, and z.
+ *
+ * The layout element defines the placement of the crystals.
+ *
+ * <ul>
+ * <li>beamgap - offset from the beamline in the Y coordinate</li>
+ * <li>nx - number of crystals in X</li>
+ * <li>ny - number of crystals in Y along each side of beam</li>
+ * <li>dface - distance from origin to the face of the calorimeter along X</li>
+ * </ul>
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Tim Nelson <[log in to unmask]>
+ *
+ * @version $Id: HPSEcal.java,v 1.12 2011/07/18 21:01:53 jeremy Exp $
+ */
+public class HPSEcal extends LCDDSubdetector
+{
+ // Tolerance factor for moving crystals to appropriate place in mom volume.
+ static final double tolerance = 0.1;
+
+ // Tolerance factor for separating crystals to avoid overlaps.
+ static final double crystalTolerance = 0.1;
+
+ HPSEcal(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
+ {
+ if (sens == null)
+ throw new RuntimeException("SensitiveDetector is null!");
+
+ // Crystal dimensions.
+ Element dimensions = node.getChild("dimensions");
+ double dx1 = dimensions.getAttribute("x1").getDoubleValue();
+ double dx2 = dimensions.getAttribute("x2").getDoubleValue();
+ double dy1 = dimensions.getAttribute("y1").getDoubleValue();
+ double dy2 = dimensions.getAttribute("y2").getDoubleValue();
+ double dz = dimensions.getAttribute("z").getDoubleValue();
+
+ // Crystal material.
+ Element mat = node.getChild("material");
+ String materialName = mat.getAttributeValue("name");
+
+ // Layout parameters.
+ Element layout = node.getChild("layout");
+ double beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ int nx = layout.getAttribute("nx").getIntValue();
+ int ny = layout.getAttribute("ny").getIntValue();
+ double dface = layout.getAttribute("dface").getDoubleValue();
+
+ // Setup crystal logical volume.
+ Trapezoid crystalTrap = new Trapezoid("crystal_trap", dx1, dx2, dy1, dy2, dz);
+ Volume crystalLogVol = new Volume("crystal_volume", crystalTrap, lcdd.getMaterial(materialName));
+ crystalLogVol.setSensitiveDetector(sens);
+
+ lcdd.add(crystalTrap);
+ lcdd.add(crystalLogVol);
+
+ // Mother volume dimensions.
+ double mx, my, mz;
+ double margin = 1.1;
+ mx = nx*Math.max(dx2,dx1)*margin;
+ my = ny*Math.max(dy2, dy1)*margin;
+ mz = dz*margin;
+
+ // Envelope box and logical volume for one section of ECal.
+ Box momBox = new Box("ecal_env_box", mx*2, my*2, mz*2);
+ Volume momVol = new Volume("ecal_env_volume", momBox, lcdd.getMaterial("Air"));
+
+ lcdd.add(momBox);
+ lcdd.add(momVol);
+
+ // Slope of the trapezoid side in X.
+ double sx = (dx2-dx1)/(2*dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in X. Rotation about Y axis.
+ double dthetay = atan(sx);
+
+ // Slope of the trapezoid side in Y.
+ double sy = (dy2-dy1)/(2*dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in Y. Rotation about X axis.
+ double dthetax = atan(sx);
+
+ // Distance between (virtual) angular origin and center of trapezoid in X.
+ double z0x = dx1/sx+dz;
+
+ // Distance between (virtual) angular origin and center of trapezoid in Y.
+ double z0y = dy1/sy+dz;
+
+ // Odd or even number of crystals in X.
+ boolean oddx = (nx % 2 != 0);
+
+ // Calculate number of X for loop.
+ if (oddx)
+ {
+ nx -= 1;
+ nx /= 2;
+ }
+ else
+ {
+ nx /= 2;
+ }
+
+ double ycorrtot = 0;
+ double zcorrtoty = 0;
+
+ Define define = lcdd.getDefine();
+
+ for (int iy=1; iy<=ny; iy++)
+ {
+ double zcorrtotx = 0;
+ double xcorrtot = 0;
+
+ int coeffy = 2*iy-1;
+ double thetax = coeffy*dthetax;
+ double zcorry = dy1*(2*sin(coeffy*dthetax));
+ double ycorr = zcorry*tan((coeffy-1)*dthetax);
+ double ycenter = z0y*sin(coeffy*dthetax)+ycorr+ycorrtot+(crystalTolerance*iy);
+
+ for (int ix=0; ix<=nx; ix++)
+ {
+ // Coefficient for even/odd crystal
+ int coeffx = 2*ix;
+ if (!oddx)
+ {
+ coeffx -= 1;
+ // For even number of crystals, the 0th is skipped.
+ if (ix==0)
+ continue;
+ }
+
+ // Set parameters for next crystal placement.
+ // FIXME Need documentation here.
+ double thetay = coeffx*dthetay;
+ double zcorrx = dx1*(2*sin(coeffx*dthetay));
+ double xcorr = zcorrx*tan((coeffx-1)*dthetay);
+ double xcenter = z0x*sin(coeffx*dthetay)+xcorr+xcorrtot+(crystalTolerance*ix);
+ double zcenter = z0y*(cos(coeffy*dthetax)-1)+z0x*(cos(coeffx*dthetay)-1)+zcorrx+zcorrtotx+zcorry+zcorrtoty;
+ zcenter += dz;
+
+ double thetaz = 0;
+
+ String baseName = "crystal"+ix+"-"+iy;
+
+ // Transform of positive.
+ Position ipos =
+ new Position(baseName+"_pos_pos", xcenter, ycenter-my+tolerance, zcenter-mz+tolerance);
+ Rotation irot =
+ new Rotation(baseName+"_rot_pos", thetax, -thetay, thetaz);
+
+ define.addPosition(ipos);
+ define.addRotation(irot);
+
+ // Place positive crystal.
+ PhysVol posCrystalPlacement = new PhysVol(crystalLogVol, momVol, ipos, irot);
+
+ // Add volume IDs.
+ posCrystalPlacement.addPhysVolID("ix", ix);
+ posCrystalPlacement.addPhysVolID("iy", iy);
+
+ // DEBUG
+ System.out.println(ix + ", " + iy);
+
+ // Reflection to negative.
+ if (ix != 0)
+ {
+ // Transform of negative.
+ Position iposneg =
+ new Position(baseName+"_pos_neg", -xcenter, ycenter-my+tolerance, zcenter-mz+tolerance);
+ Rotation irotneg =
+ new Rotation(baseName+"_rot_neg", thetax, thetay, thetaz);
+
+ define.addPosition(iposneg);
+ define.addRotation(irotneg);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacement = new PhysVol(crystalLogVol, momVol, iposneg, irotneg);
+
+ // Add volume IDs.
+ negCrystalPlacement.addPhysVolID("ix", -ix);
+ negCrystalPlacement.addPhysVolID("iy", iy);
+
+ // DEBUG
+ System.out.println(-ix + ", " + iy);
+ }
+
+ // Increment running X and Z totals and include tolerance to avoid overlaps.
+ xcorrtot += xcorr;
+ zcorrtotx += zcorrx;
+ }
+
+ // Increment running Y totals.
+ ycorrtot += ycorr;
+ zcorrtoty += zcorry;
+ }
+
+ // Get mother volume for envelope.
+ Volume world = lcdd.pickMotherVolume(this);
+
+ // Place the top section.
+ Position mpostop = new Position(momVol.getVolumeName() + "_top_pos", dface+mz, 0, my+beamgap);
+ Rotation mrottop = new Rotation(momVol.getVolumeName() + "_top_rot", 0, -Math.PI/2, (3*Math.PI)/2);
+ define.addPosition(mpostop);
+ define.addRotation(mrottop);
+ PhysVol topSide = new PhysVol(momVol, world, mpostop, mrottop);
+ topSide.addPhysVolID("system", this.getSystemID());
+ topSide.addPhysVolID("side", 1);
+
+ // Place the bottom section.
+ Position mposbot = new Position(momVol.getVolumeName() + "_bot_pos", dface+mz, 0, -my-beamgap);
+ Rotation mrotbot = new Rotation(momVol.getVolumeName() + "_bot_rot", 0, -Math.PI/2, Math.PI/2);
+ define.addPosition(mposbot);
+ define.addRotation(mrotbot);
+ PhysVol botSide = new PhysVol(momVol, world, mposbot, mrotbot);
+ botSide.addPhysVolID("system", this.getSystemID());
+ botSide.addPhysVolID("side", -1);
+
+ // Make the section box invisible.
+ momVol.setVisAttributes(lcdd.getVisAttributes("InvisibleWithDaughters"));
+ }
+
+ public boolean isCalorimeter()
+ {
+ return true;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal2.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal2.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal2.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,253 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import static java.lang.Math.atan;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import static java.lang.Math.tan;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.Define;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * LCDD model for the HPS inner ECal.
+ *
+ * Coordinate System Notes:
+ *
+ * Beam travels in +X direction.
+ * Magnetic field is -Z (????).
+ * Y is the beam bend plane.
+ *
+ * The dimensions element defines the crystal HALF dimensions: x1, x2, y1, y2, and z.
+ *
+ * The layout element defines the placement of the crystals.
+ *
+ * <ul>
+ * <li>beamgap - offset from the beamline in the Y coordinate</li>
+ * <li>nx - number of crystals in X</li>
+ * <li>ny - number of crystals in Y along each side of beam</li>
+ * <li>dface - distance from origin to the face of the calorimeter along X</li>
+ * </ul>
+ *
+ * @author Jeremy McCormick
+ * @author Tim Nelson
+ *
+ * @version $Id: HPSEcal2.java,v 1.1 2011/07/14 22:45:55 jeremy Exp $
+ */
+public class HPSEcal2 extends LCDDSubdetector
+{
+ // Tolerance factor for moving crystals to appropriate place in mom volume.
+ static final double tolerance = 0.1;
+
+ // Tolerance factor for separating crystals to avoid overlaps.
+ static final double crystalTolerance = 0.1;
+
+ HPSEcal2(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
+ {
+ if (sens == null)
+ throw new RuntimeException("SensitiveDetector is null!");
+
+ // Crystal dimensions.
+ Element dimensions = node.getChild("dimensions");
+ double dx1 = dimensions.getAttribute("x1").getDoubleValue();
+ double dx2 = dimensions.getAttribute("x2").getDoubleValue();
+ double dy1 = dimensions.getAttribute("y1").getDoubleValue();
+ double dy2 = dimensions.getAttribute("y2").getDoubleValue();
+ double dz = dimensions.getAttribute("z").getDoubleValue();
+
+ // Crystal material.
+ Element mat = node.getChild("material");
+ String materialName = mat.getAttributeValue("name");
+
+ // Layout parameters.
+ Element layout = node.getChild("layout");
+ double beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ int nx = layout.getAttribute("nx").getIntValue();
+ int ny = layout.getAttribute("ny").getIntValue();
+ double dface = layout.getAttribute("dface").getDoubleValue();
+
+ // Setup crystal logical volume.
+ Trapezoid crystalTrap = new Trapezoid("crystal_trap", dx1, dx2, dy1, dy2, dz);
+ Volume crystalLogVol = new Volume("crystal_volume", crystalTrap, lcdd.getMaterial(materialName));
+ crystalLogVol.setSensitiveDetector(sens);
+
+ lcdd.add(crystalTrap);
+ lcdd.add(crystalLogVol);
+
+ // Mother volume dimensions.
+ double mx, my, mz;
+ double margin = 1.1;
+ mx = nx*Math.max(dx2,dx1)*margin;
+ my = ny*Math.max(dy2, dy1)*margin;
+ mz = dz*margin;
+
+ // Envelope box and logical volume for one section of ECal.
+ Box momBox = new Box("ecal_env_box", mx*2, my*2, mz*2);
+ Volume momVol = new Volume("ecal_env_volume", momBox, lcdd.getMaterial("Air"));
+
+ lcdd.add(momBox);
+ lcdd.add(momVol);
+
+ // Slope of the trapezoid side in X.
+ double sx = (dx2-dx1)/(2*dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in X. Rotation about Y axis.
+ double dthetay = atan(sx);
+
+ // Slope of the trapezoid side in Y.
+ double sy = (dy2-dy1)/(2*dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in Y. Rotation about X axis.
+ double dthetax = atan(sx);
+
+ // Distance between (virtual) angular origin and center of trapezoid in X.
+ double z0x = dx1/sx+dz;
+
+ // Distance between (virtual) angular origin and center of trapezoid in Y.
+ double z0y = dy1/sy+dz;
+
+ // Odd or even number of crystals in X.
+ boolean oddx = (nx % 2 != 0);
+
+ // Calculate number of X for loop.
+ if (oddx)
+ {
+ nx -= 1;
+ nx /= 2;
+ }
+ else
+ {
+ nx /= 2;
+ }
+
+ double ycorrtot = 0;
+ double zcorrtoty = 0;
+
+ Define define = lcdd.getDefine();
+
+ for (int iy=1; iy<=ny; iy++)
+ {
+ double zcorrtotx = 0;
+ double xcorrtot = 0;
+
+ int coeffy = 2*iy-1;
+ double thetax = coeffy*dthetax;
+ double zcorry = dy1*(2*sin(coeffy*dthetax));
+ double ycorr = zcorry*tan((coeffy-1)*dthetax);
+ double ycenter = z0y*sin(coeffy*dthetax)+ycorr+ycorrtot+(crystalTolerance*iy);
+
+ for (int ix=0; ix<=nx; ix++)
+ {
+ // Coefficient for even/odd crystal
+ int coeffx = 2*ix;
+ if (!oddx)
+ {
+ coeffx -= 1;
+ // For even number of crystals, the 0th is skipped.
+ if (ix==0)
+ continue;
+ }
+
+ // Set parameters for next crystal placement.
+ // FIXME Need documentation here.
+ double thetay = coeffx*dthetay;
+ double zcorrx = dx1*(2*sin(coeffx*dthetay));
+ double xcorr = zcorrx*tan((coeffx-1)*dthetay);
+ double xcenter = z0x*sin(coeffx*dthetay)+xcorr+xcorrtot+(crystalTolerance*ix);
+ double zcenter = z0y*(cos(coeffy*dthetax)-1)+z0x*(cos(coeffx*dthetay)-1)+zcorrx+zcorrtotx+zcorry+zcorrtoty;
+ zcenter += dz;
+
+ double thetaz = 0;
+
+ String baseName = "crystal"+ix+"-"+iy;
+
+ // Transform of positive.
+ Position ipos =
+ new Position(baseName+"_pos_pos", xcenter, ycenter-my+tolerance, zcenter-mz+tolerance);
+ Rotation irot =
+ new Rotation(baseName+"_rot_pos", thetax, -thetay, thetaz);
+
+ define.addPosition(ipos);
+ define.addRotation(irot);
+
+ // Place positive crystal.
+ PhysVol posCrystalPlacement = new PhysVol(crystalLogVol, momVol, ipos, irot);
+
+ // Add volume IDs.
+ posCrystalPlacement.addPhysVolID("ix", ix);
+ posCrystalPlacement.addPhysVolID("iy", iy);
+
+ // Reflection to negative.
+ if (ix != 0)
+ {
+ // Transform of negative.
+ Position iposneg =
+ new Position(baseName+"_pos_neg", -xcenter, ycenter-my+tolerance, zcenter-mz+tolerance);
+ Rotation irotneg =
+ new Rotation(baseName+"_rot_neg", thetax, thetay, thetaz);
+
+ define.addPosition(iposneg);
+ define.addRotation(irotneg);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacement = new PhysVol(crystalLogVol, momVol, iposneg, irotneg);
+
+ // Add volume IDs.
+ negCrystalPlacement.addPhysVolID("ix", -ix);
+ negCrystalPlacement.addPhysVolID("iy", iy);
+ }
+
+ // Increment running X and Z totals and include tolerance to avoid overlaps.
+ xcorrtot += xcorr;
+ zcorrtotx += zcorrx;
+ }
+
+ // Increment running Y totals.
+ ycorrtot += ycorr;
+ zcorrtoty += zcorry;
+ }
+
+ // Get mother volume for envelope.
+ Volume world = lcdd.pickMotherVolume(this);
+
+ // Place the top section.
+ Position mpostop = new Position(momVol.getVolumeName() + "_top_pos", 0, my+beamgap, dface+mz);
+ //Rotation mrottop = new Rotation(momVol.getVolumeName() + "_top_rot", 0, -Math.PI/2, (3*Math.PI)/2);
+ Rotation mrottop = new Rotation(momVol.getVolumeName() + "_top_rot", 0, 0, 0);
+ define.addPosition(mpostop);
+ define.addRotation(mrottop);
+ PhysVol topSide = new PhysVol(momVol, world, mpostop, mrottop);
+ topSide.addPhysVolID("system", this.getSystemID());
+ topSide.addPhysVolID("side", 1);
+
+ // Place the bottom section.
+ Position mposbot = new Position(momVol.getVolumeName() + "_bot_pos", 0, -my-beamgap, dface+mz);
+ Rotation mrotbot = new Rotation(momVol.getVolumeName() + "_bot_rot", 0, 0, Math.PI);
+ define.addPosition(mposbot);
+ define.addRotation(mrotbot);
+ PhysVol botSide = new PhysVol(momVol, world, mposbot, mrotbot);
+ botSide.addPhysVolID("system", this.getSystemID());
+ botSide.addPhysVolID("side", -1);
+
+ // Make the section box invisible.
+ momVol.setVisAttributes(lcdd.getVisAttributes("InvisibleWithDaughters"));
+ }
+
+ public boolean isCalorimeter()
+ {
+ return true;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal3.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal3.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSEcal3.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,378 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import static java.lang.Math.atan;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import static java.lang.Math.tan;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Define;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Trapezoid;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * LCDD model for the HPS inner ECal.
+ *
+ * Coordinate System defined as follows:<br>
+ *
+ * <ul>
+ * <li>Beam travels in +X direction.</li>
+ * <li>Magnetic field is in -Z.</li>
+ * <li>Y is the beam bend plane.</li>
+ * </ul>
+ *
+ * The <dimensions> element defines the crystal HALF dimensions: x1, x2, y1, y2, and z.<br>
+ *
+ * The <layout> element defines the number of crystals and (optionally) crystals to be left out.<br>
+ *
+ * <ul>
+ * <li><b>beamgap</b> - offset from the beamline in the Y coordinate of the top and bottom halves</li>
+ * <li><b>beamgapTop</b> - offset from the beamline in the Y coordinate for the top half (defaults to <b>beamgap</b>)</li>
+ * <li><b>beamgapBottom</b> - offset from the beamline in the Y coordinate for the bottom half (defaults to <b>beamgap</b>)</li>
+ * <li><b>nx</b> - number of crystals in X</li>
+ * <li><b>ny</b> - number of crystals in Y along each side of beam</li>
+ * <li><b>dface</b> - distance from origin to the face of the calorimeter along Z</li>
+ * </ul>
+ *
+ * Under the layout element, <remove> tags can be included to exclude crystal placement by range. This element
+ * has the following parameters.<br>
+ *
+ * <ul>
+ * <li><b>ixmin</b> - minimum x index to exclude (inclusive)</li>
+ * <li><b>ixmax</b> - maximum x index to exclude (inclusive)</li>
+ * <li><b>iymin</b> - minimum y index to exclude (inclusive)</li>
+ * <li><b>iymax</b> - maximum y index to exclude (inclusive)</li>
+ * </ul>
+ *
+ * To be excluded, a crystal's ID must pass all four of these min/max checks.<br>
+ *
+ * @author Jeremy McCormick
+ * @author Tim Nelson
+ *
+ * @version $Id: HPSEcal3.java,v 1.9 2012/06/11 22:55:31 jeremy Exp $
+ */
+public class HPSEcal3 extends LCDDSubdetector {
+ // Tolerance factor for moving crystals to appropriate place in mom volume.
+ static final double tolerance = 0.0;
+
+ // Tolerance factor for separating crystals to avoid overlaps.
+ static final double crystalToleranceY = 0.35;
+ static final double crystalToleranceX = 0.2;
+
+ // Margin for mother volume.
+ static final double margin = 1.1;
+
+ List<CrystalRange> ranges = new ArrayList<CrystalRange>();
+
+ private static class CrystalRange {
+ int ixmin;
+ int ixmax;
+ int iymin;
+ int iymax;
+
+ CrystalRange(Element elem) throws Exception {
+ ixmin = ixmax = iymin = iymax = 0;
+
+ if (elem.getAttribute("ixmin") != null) {
+ ixmin = elem.getAttribute("ixmin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmin parameter.");
+ }
+
+ if (elem.getAttribute("ixmax") != null) {
+ ixmax = elem.getAttribute("ixmax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymin") != null) {
+ iymin = elem.getAttribute("iymin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymax") != null) {
+ iymax = elem.getAttribute("iymax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing iymax parameter.");
+ }
+ }
+ }
+
+ private boolean checkRange(int ix, int iy, List<CrystalRange> ranges) {
+ if (ranges.size() == 0)
+ return true;
+ for (CrystalRange range : ranges) {
+ if ((ix >= range.ixmin && ix <= range.ixmax) && ((iy >= range.iymin) && (iy <= range.iymax))) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ HPSEcal3(Element node) throws JDOMException {
+ super(node);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException {
+ if (sens == null)
+ throw new RuntimeException("SensitiveDetector parameter points to null.");
+
+ // Crystal dimensions.
+ Element dimensions = node.getChild("dimensions");
+ double dx1 = dimensions.getAttribute("x1").getDoubleValue();
+ double dx2 = dimensions.getAttribute("x2").getDoubleValue();
+ double dy1 = dimensions.getAttribute("y1").getDoubleValue();
+ double dy2 = dimensions.getAttribute("y2").getDoubleValue();
+ double dz = dimensions.getAttribute("z").getDoubleValue();
+
+ int system = this.getSystemID();
+
+ // Crystal material.
+ Element mat = node.getChild("material");
+ String materialName = mat.getAttributeValue("name");
+
+ // Layout parameters.
+ Element layout = node.getChild("layout");
+ double beamgap = 0;
+ if (layout.getAttribute("beamgap") != null) {
+ beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ } else {
+ if (layout.getAttribute("beamgapTop") == null || layout.getAttribute("beamgapBottom") == null) {
+ throw new RuntimeException("Missing beamgap parameter in layout element, and beamgapTop or beamgapBottom was not provided.");
+ }
+ }
+ double beamgapTop = beamgap;
+ if (layout.getAttribute("beamgapTop") != null) {
+ beamgapTop = layout.getAttribute("beamgapTop").getDoubleValue();
+ }
+ double beamgapBottom = beamgap;
+ if (layout.getAttribute("beamgapBottom") != null) {
+ beamgapBottom = layout.getAttribute("beamgapBottom").getDoubleValue();
+ }
+ int nx = layout.getAttribute("nx").getIntValue();
+ int ny = layout.getAttribute("ny").getIntValue();
+ double dface = layout.getAttribute("dface").getDoubleValue();
+
+ double tdx, tdy, tdz;
+ double bdx, bdy, bdz;
+ tdx = tdy = tdz = bdx = bdy = bdz = 0.;
+ Element topElement = layout.getChild("top");
+ Element bottomElement = layout.getChild("bottom");
+ if (topElement != null) {
+ if (topElement.getAttribute("dx") != null)
+ tdx = topElement.getAttribute("dx").getDoubleValue();
+ if (topElement.getAttribute("dy") != null)
+ tdy = topElement.getAttribute("dy").getDoubleValue();
+ if (topElement.getAttribute("dz") != null)
+ tdz = topElement.getAttribute("dz").getDoubleValue();
+ }
+ if (bottomElement != null) {
+ if (bottomElement.getAttribute("dx") != null)
+ bdx = bottomElement.getAttribute("dx").getDoubleValue();
+ if (bottomElement.getAttribute("dy") != null)
+ bdy = bottomElement.getAttribute("dy").getDoubleValue();
+ if (bottomElement.getAttribute("dz") != null)
+ bdz = bottomElement.getAttribute("dz").getDoubleValue();
+ }
+
+ // Setup range of indices to be skipped.
+ for (Object obj : layout.getChildren("remove")) {
+ Element remove = (Element) obj;
+ try {
+ ranges.add(new CrystalRange(remove));
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ // Setup crystal logical volume.
+ Trapezoid crystalTrap = new Trapezoid("crystal_trap", dx1, dx2, dy1, dy2, dz);
+ Volume crystalLogVol = new Volume("crystal_volume", crystalTrap, lcdd.getMaterial(materialName));
+ crystalLogVol.setSensitiveDetector(sens);
+
+ // Set vis attributes on crystal log vol.
+ setVisAttributes(lcdd, this.getNode(), crystalLogVol);
+
+ // Add shape and log vol to lcdd.
+ lcdd.add(crystalTrap);
+ lcdd.add(crystalLogVol);
+
+ // Place crystals in world volume.
+ Volume world = lcdd.pickMotherVolume(this);
+
+ //
+ // Now we calculate parameters for crystal placement...
+ //
+
+ // Slope of the trapezoid side in X.
+ double sx = (dx2 - dx1) / (2 * dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in X. Rotation about Y axis.
+ double dthetay = atan(sx);
+
+ // Slope of the trapezoid side in Y.
+ double sy = (dy2 - dy1) / (2 * dz);
+
+ // Angle of the side of the trapezoid w.r.t. center line in Y. Rotation about X axis.
+ double dthetax = atan(sx);
+
+ // Distance between (virtual) angular origin and center of trapezoid in X.
+ double z0x = dx1 / sx + dz;
+
+ // Distance between (virtual) angular origin and center of trapezoid in Y.
+ double z0y = dy1 / sy + dz;
+
+ // Odd or even number of crystals in X.
+ boolean oddx = (nx % 2 != 0);
+
+ // Calculate number of X for loop.
+ if (oddx) {
+ nx -= 1;
+ nx /= 2;
+ } else {
+ nx /= 2;
+ }
+
+ double ycorrtot = 0;
+ double zcorrtoty = 0;
+
+ Define define = lcdd.getDefine();
+
+ for (int iy = 1; iy <= ny; iy++) {
+ double zcorrtotx = 0;
+ double xcorrtot = 0;
+
+ int coeffy = 2 * iy - 1;
+ double thetax = coeffy * dthetax;
+ double zcorry = dy1 * (2 * sin(coeffy * dthetax));
+ double ycorr = zcorry * tan((coeffy - 1) * dthetax);
+ double ycenter = z0y * sin(coeffy * dthetax) + ycorr + ycorrtot + (crystalToleranceY * iy);
+ double thetaz = 0;
+
+ for (int ix = 0; ix <= nx; ix++) {
+ // Coefficient for even/odd crystal
+ int coeffx = 2 * ix;
+ if (!oddx) {
+ coeffx -= 1;
+ // For even number of crystals, the 0th is skipped.
+ if (ix == 0)
+ continue;
+ }
+
+ // Set parameters for next crystal placement.
+ double thetay = coeffx * dthetay;
+ double zcorrx = dx1 * (2 * sin(coeffx * dthetay));
+ double xcorr = zcorrx * tan((coeffx - 1) * dthetay);
+ double xcenter = z0x * sin(coeffx * dthetay) + xcorr + xcorrtot + (crystalToleranceX * ix);
+ double zcenter = z0y * (cos(coeffy * dthetax) - 1) + z0x * (cos(coeffx * dthetay) - 1) + zcorrx + zcorrtotx + zcorry + zcorrtoty;
+ zcenter += dz;
+
+ String baseName = "crystal" + ix + "-" + iy;
+
+ //
+ // Bottom section.
+ //
+
+ if (checkRange(ix, -iy, ranges)) {
+ // Transform of positive bottom crystal.
+ Position iposBot = new Position(baseName + "_pos_pos_bot", xcenter + bdx, -(beamgapBottom + ycenter + tolerance) + bdy, zcenter + tolerance + dface + bdz);
+
+ //System.out.println("iposBot = " + iposBot.x() + ", " + iposBot.y() + " , " + iposBot.z() + " --> " + ix + ", " + -iy);
+ Rotation irotBot = new Rotation(baseName + "_rot_pos_bot", -thetax, -thetay, thetaz);
+ define.addPosition(iposBot);
+ define.addRotation(irotBot);
+
+ // Place positive crystal.
+ PhysVol posCrystalPlacementBot = new PhysVol(crystalLogVol, world, iposBot, irotBot);
+
+ // Add volume IDs.
+ posCrystalPlacementBot.addPhysVolID("system", system);
+ posCrystalPlacementBot.addPhysVolID("ix", ix);
+ posCrystalPlacementBot.addPhysVolID("iy", -iy);
+ }
+
+ // Reflection to negative.
+ if (ix != 0) {
+ if (checkRange(-ix, -iy, ranges)) {
+ // Transform of negative.
+ Position iposnegBot = new Position(baseName + "_pos_neg_bot", -xcenter + bdx, -(beamgapBottom + ycenter + tolerance) + bdy, zcenter + tolerance + dface + bdz);
+ //System.out.println("iposnegBot = " + iposnegBot.x() + ", " + iposnegBot.y() + " , " + iposnegBot.z() + " --> " + -ix + ", " + -iy);
+ Rotation irotnegBot = new Rotation(baseName + "_rot_neg_bot", -thetax, thetay, thetaz);
+
+ define.addPosition(iposnegBot);
+ define.addRotation(irotnegBot);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacementBot = new PhysVol(crystalLogVol, world, iposnegBot, irotnegBot);
+
+ // Add volume IDs.
+ negCrystalPlacementBot.addPhysVolID("system", system);
+ negCrystalPlacementBot.addPhysVolID("ix", -ix);
+ negCrystalPlacementBot.addPhysVolID("iy", -iy);
+ }
+ }
+
+ if (checkRange(ix, iy, ranges)) {
+ // Transform of positive top crystal.
+ Position iposTop = new Position(baseName + "_pos_pos_top", xcenter + tdx, beamgapTop + ycenter + tolerance + tdy, zcenter + tolerance + dface + tdz);
+ //System.out.println("iposTop = " + iposTop.x() + ", " + iposTop.y() + " , " + iposTop.z() + " --> " + ix + ", " + iy);
+ Rotation irotTop = new Rotation(baseName + "_rot_pos_top", thetax, -thetay, thetaz);
+ define.addPosition(iposTop);
+ define.addRotation(irotTop);
+
+ // Place positive top crystal.
+ PhysVol posCrystalPlacementTop = new PhysVol(crystalLogVol, world, iposTop, irotTop);
+
+ // Add volume IDs.
+ posCrystalPlacementTop.addPhysVolID("system", system);
+ posCrystalPlacementTop.addPhysVolID("ix", ix);
+ posCrystalPlacementTop.addPhysVolID("iy", iy);
+ }
+
+ // Reflection to negative.
+ if (ix != 0) {
+ if (checkRange(-ix, iy, ranges)) {
+ // Transform of negative.
+ Position iposnegTop = new Position(baseName + "_pos_neg_top", -xcenter + tdx, beamgapTop + ycenter + tolerance + tdy, zcenter + tolerance + dface + tdz);
+ //System.out.println("iposTop = " + iposnegTop.x() + ", " + iposnegTop.y() + " , " + iposnegTop.z() + " --> " + -ix + ", " + iy);
+ Rotation irotnegTop = new Rotation(baseName + "_rot_neg_top", thetax, thetay, thetaz);
+
+ define.addPosition(iposnegTop);
+ define.addRotation(irotnegTop);
+
+ // Place negative crystal.
+ PhysVol negCrystalPlacementTop = new PhysVol(crystalLogVol, world, iposnegTop, irotnegTop);
+
+ // Add volume IDs.
+ negCrystalPlacementTop.addPhysVolID("system", system);
+ negCrystalPlacementTop.addPhysVolID("ix", -ix);
+ negCrystalPlacementTop.addPhysVolID("iy", iy);
+ }
+ }
+
+ // Increment running X and Z totals and include tolerance to avoid overlaps.
+ xcorrtot += xcorr;
+ zcorrtotx += zcorrx;
+ }
+
+ // Increment running Y totals.
+ ycorrtot += ycorr;
+ zcorrtoty += zcorry;
+ }
+ }
+
+ public boolean isCalorimeter() {
+ return true;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,122 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.Material;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * @author jeremym
+ * @version $Id: HPSMuonCalorimeter.java,v 1.5 2013/01/25 00:13:44 jeremy Exp $
+ */
+public class HPSMuonCalorimeter extends LCDDSubdetector
+{
+
+ HPSMuonCalorimeter(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
+ {
+
+ String name = node.getAttributeValue("name");
+ int id = node.getAttribute("id").getIntValue();
+ Volume mother = lcdd.pickMotherVolume(this);
+
+ for (Object layerObject : node.getChildren("layer")) {
+
+ Element layer = (Element) layerObject;
+ int layerId = layer.getAttribute("id").getIntValue();
+
+ int slice = 1;
+ for (Object boxObject : layer.getChildren("box")) {
+
+ Element element = (Element) boxObject;
+
+ double x, y, z, px, py, pz, rx, ry, rz;
+ x = y = z = px = py = pz = rx = ry = rz = 0.;
+
+ if (element.getAttribute("x") != null) {
+ x = element.getAttribute("x").getDoubleValue();
+ } else {
+ throw new RuntimeException("x is required.");
+ }
+ if (element.getAttribute("y") != null) {
+ y = element.getAttribute("y").getDoubleValue();
+ } else {
+ throw new RuntimeException("y is required.");
+ }
+ if (element.getAttribute("z") != null) {
+ z = element.getAttribute("z").getDoubleValue();
+ } else {
+ throw new RuntimeException("z is required.");
+ }
+
+ if (element.getAttribute("px") != null)
+ px = element.getAttribute("px").getDoubleValue();
+ if (element.getAttribute("py") != null)
+ py = element.getAttribute("py").getDoubleValue();
+ if (element.getAttribute("pz") != null)
+ pz = element.getAttribute("pz").getDoubleValue();
+
+ if (element.getAttribute("rx") != null)
+ rx = element.getAttribute("rx").getDoubleValue();
+ if (element.getAttribute("ry") != null)
+ ry = element.getAttribute("ry").getDoubleValue();
+ if (element.getAttribute("rz") != null)
+ rz = element.getAttribute("rz").getDoubleValue();
+
+ String materialString = element.getAttributeValue("material");
+ Material material = lcdd.getMaterial(materialString);
+
+ String shapeBaseName = name + "_layer" + layerId + "_sublayer" + slice;
+
+ Box box = new Box(shapeBaseName + "_box", x, y, z);
+ lcdd.add(box);
+
+ Position pos = new Position(shapeBaseName + "_pos", px, py, pz);
+ lcdd.add(pos);
+
+ Rotation rot = new Rotation(shapeBaseName + "_rot", rx, ry, rz);
+ lcdd.add(rot);
+
+ Volume vol = new Volume(shapeBaseName + "_vol", box, material);
+
+ boolean sensitive = false;
+ if (element.getAttribute("sensitive") != null)
+ sensitive = element.getAttribute("sensitive").getBooleanValue();
+
+ if (sensitive) {
+ vol.setSensitiveDetector(sens);
+ }
+
+ lcdd.add(vol);
+
+ PhysVol physVol = new PhysVol(vol, mother, pos, rot);
+ physVol.addPhysVolID("layer", layerId);
+ physVol.addPhysVolID("slice", slice);
+ if (py >= 0) {
+ physVol.addPhysVolID("side", 1);
+ } else {
+ physVol.addPhysVolID("side", -1);
+ }
+ physVol.addPhysVolID("system", id);
+
+ ++slice;
+ }
+ }
+
+ }
+
+ public boolean isCalorimeter()
+ {
+ return true;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter2.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter2.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSMuonCalorimeter2.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,55 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+public class HPSMuonCalorimeter2 extends LCDDSubdetector
+{
+ HPSMuonCalorimeter2(Element e) throws JDOMException
+ {
+ super(e);
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sens) throws JDOMException
+ {
+ String name = node.getAttributeValue("name");
+ System.out.println("HPSMuonCalorimeter2.addToLCDD - " + name);
+ int id = node.getAttribute("id").getIntValue();
+ Volume mother = lcdd.pickMotherVolume(this);
+
+ Element parameters = node.getChild("parameters");
+ if (parameters == null) {
+ throw new RuntimeException("parameters element missing");
+ }
+
+ double frontFaceToTarget = parameters.getAttribute("front_face_to_target").getDoubleValue();
+ double deadZoneAngle = parameters.getAttribute("dead_zone_angle").getDoubleValue();
+ double stripThickness = parameters.getAttribute("strip_thickness").getDoubleValue();
+ double stripSpacingZ = parameters.getAttribute("strip_spacing_z").getDoubleValue();
+ double stripSpacingY = parameters.getAttribute("strip_spacing_y").getDoubleValue();
+ double stripSpacingX = parameters.getAttribute("strip_spacing_x").getDoubleValue();
+
+ System.out.println("frontFaceToTarget = " + frontFaceToTarget);
+ System.out.println("deadZoneAngle = " + deadZoneAngle);
+ System.out.println("stripThickness = " + stripThickness);
+ System.out.println("stripSpacingX = " + stripSpacingX);
+ System.out.println("stripSpacingY = " + stripSpacingY);
+ System.out.println("stripSpacingZ = " + stripSpacingZ);
+
+ for (Object layerObject : node.getChildren("layer")) {
+ Element layerElement = (Element)layerObject;
+ int layerId = layerElement.getAttribute("id").getIntValue();
+ System.out.println("layer = " + layerId);
+ for (Object sliceObject : layerElement.getChildren("slice")) {
+ Element sliceElement = (Element)sliceObject;
+ if (sliceElement.getAttribute("thickness") != null) {
+ double thickness = sliceElement.getAttribute("thickness").getDoubleValue();
+ System.out.println("slice thickness = " + thickness);
+ }
+ }
+ }
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,512 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.Material;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ * An LCDD converter for a Silicon endcap tracker model based on Bill Cooper's design from <a href=
+ * "http://ilcagenda.linearcollider.org/materialDisplay.py?contribId=58&sessionId=1&materialId=slides&confId=2784"
+ * >Boulder SiD Workshop 2008</a>.
+ *
+ * @author jeremym
+ */
+public class HPSTracker extends LCDDSubdetector
+{
+
+ Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ Map<String, Volume> modules = new HashMap<String, Volume>();
+ Material vacuum;
+
+ public HPSTracker(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ public boolean isTracker()
+ {
+ return true;
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sd) throws JDOMException
+ {
+ int sysId = node.getAttribute("id").getIntValue();
+ String subdetName = node.getAttributeValue("name");
+ vacuum = lcdd.getMaterial("Vacuum");
+ boolean reflect;
+
+ if (node.getAttribute("reflect") != null)
+ {
+ reflect = node.getAttribute("reflect").getBooleanValue();
+ }
+ else
+ {
+ reflect = true;
+ }
+
+
+ for (Iterator i = node.getChildren("module").iterator(); i.hasNext();)
+ {
+ Element module = (Element) i.next();
+ String moduleName = module.getAttributeValue("name");
+ moduleParameters.put(moduleName, new ModuleParameters(module));
+ modules.put(moduleName, makeModule(moduleParameters.get(moduleName), sd, lcdd));
+ }
+
+ // layer
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();)
+ {
+ // Modules are numbered from 0 starting in each layer.
+ int moduleNumber = 0;
+
+ Element layerElement = (Element) i.next();
+ int layerId = layerElement.getAttribute("id").getIntValue();
+
+ System.out.println("<layer id=\"" + layerId + "\">");
+
+ int ringCount = 0;
+
+ // quadrant (???)
+ for (Iterator j = layerElement.getChildren("quadrant").iterator(); j.hasNext();)
+ {
+ Element ringElement = (Element) j.next();
+
+ double zLayer = ringElement.getAttribute("z").getDoubleValue();
+ double dz = ringElement.getAttribute("dz").getDoubleValue();
+ double xStart = ringElement.getAttribute("xStart").getDoubleValue();
+ double xStep = ringElement.getAttribute("xStep").getDoubleValue();
+ int nx = ringElement.getAttribute("nx").getIntValue();
+ double yStart = ringElement.getAttribute("yStart").getDoubleValue();
+ int ny = ringElement.getAttribute("ny").getIntValue();
+ double yStep = ringElement.getAttribute("yStep").getDoubleValue();
+ double top_phi0 = 0;
+ if (ringElement.getAttribute("top_phi0") != null)
+ {
+ top_phi0 = ringElement.getAttribute("top_phi0").getDoubleValue();
+ }
+ double bot_phi0 = 0;
+ if (ringElement.getAttribute("bot_phi0") != null)
+ {
+ bot_phi0 = ringElement.getAttribute("bot_phi0").getDoubleValue();
+ }
+ double theta = 0;
+ if (ringElement.getAttribute("theta") != null)
+ {
+ theta = ringElement.getAttribute("theta").getDoubleValue();
+ }
+
+ String module = ringElement.getAttributeValue("module");
+
+ Volume moduleVolume = modules.get(module);
+
+ if (moduleVolume == null)
+ {
+ throw new RuntimeException("Module " + module + " was not found.");
+ }
+
+ double x, y, z;
+ z = zLayer;
+ x = xStart;
+
+ // nx
+ for (int k = 0; k < nx; k++ )
+ {
+ y = yStart;
+ // ny
+ for (int kk = 0; kk < ny; kk++ )
+ {
+ String moduleBaseName = subdetName + "_layer" + layerId + "_module" + moduleNumber;
+
+ Position p = new Position(moduleBaseName + "_position");
+
+ p.setX(x);
+ p.setY(y);
+ p.setZ(z + dz);
+ //System.out.println("layer, module = " + layerId + ", " + moduleNumber);
+ //System.out.println("module pos = " + x + " " + y + " " + z);
+ Rotation rot = new Rotation(moduleBaseName + "_rotation");
+ rot.setX(0);
+ rot.setY(theta);
+ //rot.setZ(phi0);
+ // Y side along world's X axis.
+ // FIXME Should phi0 actually be subtracted???
+ rot.setZ(-(Math.PI / 2 + top_phi0));
+ //System.out.println("module rot = " + 0 + ", " + theta + "," + -(Math.PI / 2 + top_phi0));
+
+ lcdd.add(p);
+ lcdd.add(rot);
+
+ PhysVol pv = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), p, rot);
+ pv.addPhysVolID("system", sysId);
+ pv.addPhysVolID("barrel", 0);
+ pv.addPhysVolID("layer", layerId);
+ pv.addPhysVolID("module", moduleNumber);
+
+ System.out.print(" <module_placement name=\"" + module + "\" ");
+ System.out.print("id=\"" + moduleNumber + "\" ");
+ System.out.print("x=\"" + p.getAttribute("x").getDoubleValue() + "\" ");
+ System.out.print("y=\"" + p.getAttribute("y").getDoubleValue() + "\" ");
+ System.out.print("z=\"" + p.getAttribute("z").getDoubleValue() + "\" ");
+ System.out.print("rx=\"" + rot.getAttribute("x").getDoubleValue() + "\" ");
+ System.out.print("ry=\"" + rot.getAttribute("y").getDoubleValue() + "\" ");
+ System.out.print("rz=\"" + rot.getAttribute("z").getDoubleValue() + "\"/>");
+ System.out.println();
+
+ ++moduleNumber;
+
+ if (reflect)
+ {
+ Position pr = new Position(moduleBaseName + "_reflect_position");
+ pr.setX(x);
+ pr.setY(-y);
+ pr.setZ(z + dz);
+ //System.out.println("module @ " + x + " " + -y + " " + (z + dz));
+ Rotation rotr = new Rotation(moduleBaseName + "_reflect_rotation");
+ rotr.setX(0);
+ rotr.setY(theta);
+ rotr.setZ(-Math.PI/2 - bot_phi0);
+
+ lcdd.add(pr);
+ lcdd.add(rotr);
+
+ PhysVol pvr = new PhysVol(moduleVolume, lcdd.getTrackingVolume(), pr, rotr);
+ pvr.addPhysVolID("system", sysId);
+ pvr.addPhysVolID("barrel", 0);
+ pvr.addPhysVolID("layer", layerId);
+ pvr.addPhysVolID("module", moduleNumber);
+
+ System.out.print(" <module_placement name=\"" + module + "\" ");
+ System.out.print("id=\"" + moduleNumber + "\" ");
+ System.out.print("x=\"" + pr.getAttribute("x").getDoubleValue() + "\" ");
+ System.out.print("y=\"" + pr.getAttribute("y").getDoubleValue() + "\" ");
+ System.out.print("z=\"" + pr.getAttribute("z").getDoubleValue() + "\" ");
+ System.out.print("rx=\"" + rotr.getAttribute("x").getDoubleValue() + "\" ");
+ System.out.print("ry=\"" + rotr.getAttribute("y").getDoubleValue() + "\" ");
+ System.out.print("rz=\"" + rotr.getAttribute("z").getDoubleValue() + "\"/>");
+ System.out.println();
+
+ ++moduleNumber;
+ }
+
+ dz = -dz;
+ y += yStep;
+ }
+ x += xStep;
+ }
+ }
+ System.out.println("</layer>");
+ }
+ }
+
+ private Volume makeModule(ModuleParameters params, SensitiveDetector sd, LCDD lcdd)
+ {
+ double thickness = params.getThickness();
+ double x, y;
+ //x = params.getDimension(0);
+ //y = params.getDimension(1);
+ y = params.getDimension(0); // Y is in X plane in world coordinates.
+ x = params.getDimension(1); // X is in Y plane in world coordinates.
+ //System.out.println("making module with x = " + x + " and y = " + y);
+ Box box = new Box(params.getName() + "Box", x, y, thickness);
+ lcdd.add(box);
+
+ Volume moduleVolume = new Volume(params.getName() + "Volume", box, vacuum);
+ makeModuleComponents(moduleVolume, params, sd, lcdd);
+ lcdd.add(moduleVolume);
+
+ if (params.getVis() != null)
+ {
+ moduleVolume.setVisAttributes(lcdd.getVisAttributes(params.getVis()));
+ }
+
+ return moduleVolume;
+ }
+
+ private void makeModuleComponents(Volume moduleVolume, ModuleParameters moduleParameters, SensitiveDetector sd, LCDD lcdd)
+ {
+ Box envelope = (Box) lcdd.getSolid(moduleVolume.getSolidRef());
+
+ double moduleX = envelope.getX();
+ double moduleY = envelope.getY();
+
+ double posZ = -moduleParameters.getThickness() / 2;
+
+ String moduleName = moduleVolume.getVolumeName();
+
+ int sensor = 0;
+ for (ModuleComponentParameters component : moduleParameters)
+ {
+
+ double thickness = component.getThickness();
+
+ Material material = null;
+ try
+ {
+ material = lcdd.getMaterial(component.getMaterialName());
+ }
+ catch (JDOMException except)
+ {
+ throw new RuntimeException(except);
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+
+ posZ += thickness / 2;
+
+ String componentName = moduleName + "_component" + componentNumber;
+
+ //System.out.println("making " + componentName + " with x = " + moduleX + " and y = " + moduleY);
+ Box componentBox = new Box(componentName + "Box", moduleX, moduleY, thickness);
+ lcdd.add(componentBox);
+
+ Volume componentVolume = new Volume(componentName, componentBox, material);
+
+ Position position = new Position(componentName + "_position", 0., 0., posZ);
+ lcdd.add(position);
+ Rotation rotation = new Rotation(componentName + "_rotation", 0., 0., 0.);
+ lcdd.add(rotation);
+
+ PhysVol pv = new PhysVol(componentVolume, moduleVolume, position, rotation);
+ pv.addPhysVolID("component", componentNumber);
+
+ if (sensitive)
+ {
+ if (sensor > 1)
+ {
+ throw new RuntimeException("Maximum of 2 sensors per module.");
+ }
+
+ // Build a child sensor volume to allow dead areas.
+
+ String sensorName = componentName + "Sensor" + sensor;
+
+ // Flipped these around!!!
+ double sensorX = component.getDimensionY();
+ double sensorY = component.getDimensionX();
+ /*
+
+ if (sensorX > moduleX)
+ throw new RuntimeException("Sensor X dimension " + sensorX + " is too big for module.");
+
+
+ if (sensorY > moduleY)
+ throw new RuntimeException("Sensor Y dimension " + sensorY + " is too big for module.");
+ */
+
+ Box sensorBox = new Box(sensorName + "Box", sensorX, sensorY, thickness);
+ lcdd.add(sensorBox);
+
+ Volume sensorVol = new Volume(sensorName, sensorBox, material);
+ sensorVol.setSensitiveDetector(sd);
+ lcdd.add(sensorVol);
+
+ Position sensorPosition = new Position(sensorName + "Position", 0, 0, 0);
+ lcdd.add(sensorPosition);
+ Rotation sensorRotation = new Rotation(sensorName + "Rotation", 0, 0, 0);
+ lcdd.add(sensorRotation);
+
+ PhysVol sensorPhysVol = new PhysVol(sensorVol, componentVolume, sensorPosition, sensorRotation);
+ sensorPhysVol.addPhysVolID("sensor", sensor);
+
+ ++sensor;
+ }
+
+ // Add component volume after (possible) sensor child volume.
+ lcdd.add(componentVolume);
+
+ // Set vis attributes of component.
+ if (component.getVis() != null)
+ {
+ componentVolume.setVisAttributes(lcdd.getVisAttributes(component.getVis()));
+ }
+
+ // Step to next component placement position.
+ posZ += thickness / 2;
+ }
+ }
+
+ static class ModuleComponentParameters
+ {
+ protected String materialName;
+ protected double thickness;
+ protected boolean sensitive;
+ protected int componentNumber;
+ protected String vis;
+ protected double dimX, dimY;
+
+ public ModuleComponentParameters(double dimX, double dimY, double thickness, String materialName, int componentNumber, boolean sensitive, String vis)
+ {
+ this.dimX = dimX;
+ this.dimY = dimY;
+ this.thickness = thickness;
+ this.materialName = materialName;
+ this.sensitive = sensitive;
+ this.componentNumber = componentNumber;
+ this.vis = vis;
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public double getDimensionX()
+ {
+ return dimX;
+ }
+
+ public double getDimensionY()
+ {
+ return dimY;
+ }
+
+ public String getMaterialName()
+ {
+ return materialName;
+ }
+
+ public boolean isSensitive()
+ {
+ return sensitive;
+ }
+
+ public int getComponentNumber()
+ {
+ return componentNumber;
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+
+ static class ModuleParameters extends ArrayList<ModuleComponentParameters>
+ {
+ double thickness;
+ String name;
+ double dimensions[] = new double[3];
+ String vis;
+
+ public ModuleParameters(Element element)
+ {
+ name = element.getAttributeValue("name");
+
+ if (element.getAttribute("vis") != null)
+ this.vis = element.getAttribute("vis").getValue();
+
+ // Optional dimension parameters (not always present).
+ if (element.getChild("trd") != null)
+ {
+ Element trd = element.getChild("trd");
+ try
+ {
+ dimensions[0] = trd.getAttribute("x1").getDoubleValue();
+ dimensions[1] = trd.getAttribute("x2").getDoubleValue();
+ dimensions[2] = trd.getAttribute("z").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+ else if (element.getChild("box") != null)
+ {
+ Element box = element.getChild("box");
+ try
+ {
+ dimensions[0] = box.getAttribute("x").getDoubleValue();
+ dimensions[1] = box.getAttribute("y").getDoubleValue();
+ }
+ catch (DataConversionException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+
+ int cntr = 0;
+ for (Object o : element.getChildren("module_component"))
+ {
+ try
+ {
+
+ Element e = (Element) o;
+
+ double thickness = e.getAttribute("thickness").getDoubleValue();
+
+ String materialName = e.getAttributeValue("material");
+
+ boolean sensitive = false;
+ if (e.getAttribute("sensitive") != null)
+ sensitive = e.getAttribute("sensitive").getBooleanValue();
+ String componentVis = null;
+ if (e.getAttribute("vis") != null)
+ componentVis = e.getAttribute("vis").getValue();
+
+ // Sensors may have reduced dimensions for dead area.
+ double x = dimensions[0]; // default
+ double y = dimensions[1]; // default
+ if (sensitive && e.getChild("dimensions") != null)
+ {
+ Element dimensions = e.getChild("dimensions");
+ x = dimensions.getAttribute("x").getDoubleValue();
+ y = dimensions.getAttribute("y").getDoubleValue();
+ // System.out.println("x,y="+x+","+y);
+ }
+ add(new ModuleComponentParameters(x, y, thickness, materialName, cntr, sensitive, componentVis));
+ }
+ catch (JDOMException x)
+ {
+ throw new RuntimeException(x);
+ }
+ ++cntr;
+ }
+
+ calculateThickness();
+ }
+
+ public void calculateThickness()
+ {
+ thickness = 0.; // reset thickness
+ for (ModuleComponentParameters p : this)
+ {
+ thickness += p.getThickness();
+ }
+ }
+
+ public double getThickness()
+ {
+ return thickness;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public double getDimension(int i)
+ {
+ if (i > (dimensions.length - 1) || i < 0)
+ throw new RuntimeException("Invalid dimensions index: " + i);
+ return dimensions[i];
+ }
+
+ public String getVis()
+ {
+ return vis;
+ }
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,355 @@
+package org.lcsim.geometry.compact.converter.lcdd;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jdom.DataConversionException;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.geometry.compact.converter.lcdd.util.Box;
+import org.lcsim.geometry.compact.converter.lcdd.util.LCDD;
+import org.lcsim.geometry.compact.converter.lcdd.util.Material;
+import org.lcsim.geometry.compact.converter.lcdd.util.PhysVol;
+import org.lcsim.geometry.compact.converter.lcdd.util.Position;
+import org.lcsim.geometry.compact.converter.lcdd.util.Rotation;
+import org.lcsim.geometry.compact.converter.lcdd.util.SensitiveDetector;
+import org.lcsim.geometry.compact.converter.lcdd.util.Volume;
+
+/**
+ *
+ * SVT geometry for HPS Test Run.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Matt Graham <[log in to unmask]>
+ */
+public class HPSTracker2 extends LCDDSubdetector {
+
+ Map<String, ModuleParameters> moduleParameters = new HashMap<String, ModuleParameters>();
+ Map<String, Volume> modules = new HashMap<String, Volume>();
+ Material vacuum;
+
+ public HPSTracker2(Element node) throws JDOMException {
+ super(node);
+ }
+
+ public boolean isTracker() {
+ return true;
+ }
+
+ void addToLCDD(LCDD lcdd, SensitiveDetector sd) throws JDOMException {
+
+ // Get parameters.
+ int sysId = node.getAttribute("id").getIntValue();
+ String subdetName = node.getAttributeValue("name");
+ vacuum = lcdd.getMaterial("Vacuum");
+
+ // Create module logical volumes.
+ createModules(lcdd, sd);
+
+ // Create module placements in tracking volume.
+ createModulePlacements(lcdd, sysId, subdetName);
+ }
+
+ // Place modules within the tracking volume.
+ private void createModulePlacements(LCDD lcdd, int sysId, String subdetName) throws DataConversionException {
+ //Volume trackingVolume = lcdd.getTrackingVolume();
+ Volume momVolume = lcdd.pickMotherVolume(this);
+ // Loop over layers.
+ for (Iterator i = node.getChildren("layer").iterator(); i.hasNext();) {
+ Element layerElement = (Element)i.next();
+ int layerNumber = layerElement.getAttribute("id").getIntValue();
+ // Loop over modules within layer.
+ for (Iterator j = layerElement.getChildren("module_placement").iterator(); j.hasNext();) {
+
+ Element modulePlacementElement = (Element)j.next();
+ String moduleName = modulePlacementElement.getAttributeValue("name");
+ int moduleNumber = modulePlacementElement.getAttribute("id").getIntValue();
+
+ // Get the position and rotation parameters. All must be explicitly specified.
+ double x, y, z;
+ double rx, ry, rz;
+ x = modulePlacementElement.getAttribute("x").getDoubleValue();
+ y = modulePlacementElement.getAttribute("y").getDoubleValue();
+ z = modulePlacementElement.getAttribute("z").getDoubleValue();
+ rx = modulePlacementElement.getAttribute("rx").getDoubleValue();
+ ry = modulePlacementElement.getAttribute("ry").getDoubleValue();
+ rz = modulePlacementElement.getAttribute("rz").getDoubleValue();
+
+ // Place the module with position and rotation from above.
+ String modulePlacementName = subdetName + "_" + moduleName + "_layer" + layerNumber + "_module" + moduleNumber;
+ Position p = new Position(modulePlacementName + "_position", x, y, z);
+ Rotation r = new Rotation(modulePlacementName + "_rotation", rx, ry, rz);
+ lcdd.add(p);
+ lcdd.add(r);
+ //PhysVol modulePhysVol = new PhysVol(modules.get(moduleName), trackingVolume, p, r);
+ PhysVol modulePhysVol = new PhysVol(modules.get(moduleName), momVolume, p, r);
+
+ // Add identifier values to the placement volume.
+ modulePhysVol.addPhysVolID("system", sysId);
+ modulePhysVol.addPhysVolID("barrel", 0);
+ modulePhysVol.addPhysVolID("layer", layerNumber);
+ modulePhysVol.addPhysVolID("module", moduleNumber);
+ }
+ }
+ }
+
+ // Create the module logical volumes.
+ private void createModules(LCDD lcdd, SensitiveDetector sd) {
+ for (Iterator i = node.getChildren("module").iterator(); i.hasNext();) {
+ Element module = (Element) i.next();
+ String moduleName = module.getAttributeValue("name");
+ moduleParameters.put(moduleName, new ModuleParameters(module));
+ modules.put(moduleName, makeModule(moduleParameters.get(moduleName), sd, lcdd));
+ }
+ }
+
+ private Volume makeModule(ModuleParameters params, SensitiveDetector sd, LCDD lcdd) {
+ double thickness = params.getThickness();
+ double x, y;
+ // x = params.getDimension(0);
+ // y = params.getDimension(1);
+ y = params.getDimension(0); // Y is in X plane in world coordinates.
+ x = params.getDimension(1); // X is in Y plane in world coordinates.
+ // System.out.println("making module with x = " + x + " and y = " + y);
+ Box box = new Box(params.getName() + "Box", x, y, thickness);
+ lcdd.add(box);
+
+ Volume moduleVolume = new Volume(params.getName() + "Volume", box, vacuum);
+ makeModuleComponents(moduleVolume, params, sd, lcdd);
+ lcdd.add(moduleVolume);
+
+ if (params.getVis() != null) {
+ moduleVolume.setVisAttributes(lcdd.getVisAttributes(params.getVis()));
+ }
+
+ return moduleVolume;
+ }
+
+ private void makeModuleComponents(Volume moduleVolume, ModuleParameters moduleParameters, SensitiveDetector sd, LCDD lcdd) {
+ Box envelope = (Box) lcdd.getSolid(moduleVolume.getSolidRef());
+
+ double moduleX = envelope.getX();
+ double moduleY = envelope.getY();
+
+ double posZ = -moduleParameters.getThickness() / 2;
+
+ String moduleName = moduleVolume.getVolumeName();
+
+ int sensor = 0;
+ for (ModuleComponentParameters component : moduleParameters) {
+
+ double thickness = component.getThickness();
+
+ Material material = null;
+ try {
+ material = lcdd.getMaterial(component.getMaterialName());
+ } catch (JDOMException except) {
+ throw new RuntimeException(except);
+ }
+ boolean sensitive = component.isSensitive();
+ int componentNumber = component.getComponentNumber();
+
+ posZ += thickness / 2;
+
+ String componentName = moduleName + "_component" + componentNumber;
+
+ Box componentBox = new Box(componentName + "Box", moduleX, moduleY, thickness);
+ lcdd.add(componentBox);
+
+ Volume componentVolume = new Volume(componentName, componentBox, material);
+
+ Position position = new Position(componentName + "_position", 0., 0., posZ);
+ lcdd.add(position);
+ Rotation rotation = new Rotation(componentName + "_rotation", 0., 0., 0.);
+ lcdd.add(rotation);
+
+ PhysVol pv = new PhysVol(componentVolume, moduleVolume, position, rotation);
+ pv.addPhysVolID("component", componentNumber);
+
+ if (sensitive) {
+ if (sensor > 1) {
+ throw new RuntimeException("Maximum of 2 sensors per module.");
+ }
+
+ // Build a child sensor volume to allow dead areas.
+
+ String sensorName = componentName + "Sensor" + sensor;
+
+ // Flipped these around!!!
+ double sensorX = component.getDimensionY();
+ double sensorY = component.getDimensionX();
+
+ Box sensorBox = new Box(sensorName + "Box", sensorX, sensorY, thickness);
+ lcdd.add(sensorBox);
+
+ Volume sensorVol = new Volume(sensorName, sensorBox, material);
+ sensorVol.setSensitiveDetector(sd);
+ lcdd.add(sensorVol);
+
+ Position sensorPosition = new Position(sensorName + "Position", 0, 0, 0);
+ lcdd.add(sensorPosition);
+ Rotation sensorRotation = new Rotation(sensorName + "Rotation", 0, 0, 0);
+ lcdd.add(sensorRotation);
+
+ PhysVol sensorPhysVol = new PhysVol(sensorVol, componentVolume, sensorPosition, sensorRotation);
+ sensorPhysVol.addPhysVolID("sensor", sensor);
+
+ ++sensor;
+ }
+
+ // Add component volume after (possible) sensor child volume.
+ lcdd.add(componentVolume);
+
+ // Set vis attributes of component.
+ if (component.getVis() != null) {
+ componentVolume.setVisAttributes(lcdd.getVisAttributes(component.getVis()));
+ }
+
+ // Step to next component placement position.
+ posZ += thickness / 2;
+ }
+ }
+
+ private static class ModuleComponentParameters {
+ protected String materialName;
+ protected double thickness;
+ protected boolean sensitive;
+ protected int componentNumber;
+ protected String vis;
+ protected double dimX, dimY;
+
+ ModuleComponentParameters(double dimX, double dimY, double thickness, String materialName, int componentNumber, boolean sensitive, String vis) {
+ this.dimX = dimX;
+ this.dimY = dimY;
+ this.thickness = thickness;
+ this.materialName = materialName;
+ this.sensitive = sensitive;
+ this.componentNumber = componentNumber;
+ this.vis = vis;
+ }
+
+ double getThickness() {
+ return thickness;
+ }
+
+ double getDimensionX() {
+ return dimX;
+ }
+
+ double getDimensionY() {
+ return dimY;
+ }
+
+ String getMaterialName() {
+ return materialName;
+ }
+
+ boolean isSensitive() {
+ return sensitive;
+ }
+
+ int getComponentNumber() {
+ return componentNumber;
+ }
+
+ String getVis() {
+ return vis;
+ }
+ }
+
+ private static class ModuleParameters extends ArrayList<ModuleComponentParameters> {
+ double thickness;
+ String name;
+ double dimensions[] = new double[3];
+ String vis;
+
+ public ModuleParameters(Element element) {
+ name = element.getAttributeValue("name");
+
+ if (element.getAttribute("vis") != null)
+ this.vis = element.getAttribute("vis").getValue();
+
+ // Optional dimension parameters (not always present).
+ if (element.getChild("trd") != null) {
+ Element trd = element.getChild("trd");
+ try {
+ dimensions[0] = trd.getAttribute("x1").getDoubleValue();
+ dimensions[1] = trd.getAttribute("x2").getDoubleValue();
+ dimensions[2] = trd.getAttribute("z").getDoubleValue();
+ } catch (DataConversionException x) {
+ throw new RuntimeException(x);
+ }
+ } else if (element.getChild("box") != null) {
+ Element box = element.getChild("box");
+ try {
+ dimensions[0] = box.getAttribute("x").getDoubleValue();
+ dimensions[1] = box.getAttribute("y").getDoubleValue();
+ } catch (DataConversionException x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ int cntr = 0;
+ for (Object o : element.getChildren("module_component")) {
+ try {
+
+ Element e = (Element) o;
+
+ double thickness = e.getAttribute("thickness").getDoubleValue();
+
+ String materialName = e.getAttributeValue("material");
+
+ boolean sensitive = false;
+ if (e.getAttribute("sensitive") != null)
+ sensitive = e.getAttribute("sensitive").getBooleanValue();
+ String componentVis = null;
+ if (e.getAttribute("vis") != null)
+ componentVis = e.getAttribute("vis").getValue();
+
+ // Sensors may have reduced dimensions for dead area.
+ double x = dimensions[0]; // default
+ double y = dimensions[1]; // default
+ if (sensitive && e.getChild("dimensions") != null) {
+ Element dimensions = e.getChild("dimensions");
+ x = dimensions.getAttribute("x").getDoubleValue();
+ y = dimensions.getAttribute("y").getDoubleValue();
+ // System.out.println("x,y="+x+","+y);
+ }
+ add(new ModuleComponentParameters(x, y, thickness, materialName, cntr, sensitive, componentVis));
+ } catch (JDOMException x) {
+ throw new RuntimeException(x);
+ }
+ ++cntr;
+ }
+
+ calculateThickness();
+ }
+
+ void calculateThickness() {
+ thickness = 0.; // reset thickness
+ for (ModuleComponentParameters p : this) {
+ thickness += p.getThickness();
+ }
+ }
+
+ double getThickness() {
+ return thickness;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ double getDimension(int i) {
+ if (i > (dimensions.length - 1) || i < 0)
+ throw new RuntimeException("Invalid dimensions index: " + i);
+ return dimensions[i];
+ }
+
+ String getVis() {
+ return vis;
+ }
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,363 @@
+package org.lcsim.geometry.subdetector;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.util.IDEncoder;
+
+/**
+ * Reconstruction version of HPS ECal with crystal array.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Timothy Nelson <[log in to unmask]>
+ * @version $Id: HPSEcal.java,v 1.6 2011/07/28 20:20:18 jeremy Exp $
+ */
+public class HPSEcal extends AbstractSubdetector
+{
+ private int nx;
+ private int ny;
+ private double beamgap;
+ private double dface;
+ private boolean oddX;
+
+ public static class NeighborMap extends HashMap<Long,Set<Long>>
+ {
+ IIdentifierHelper helper;
+ public NeighborMap(IIdentifierHelper helper)
+ {
+ this.helper = helper;
+ }
+
+ public String toString()
+ {
+ System.out.println("NeighborMap has " + this.size() + " entries.");
+ StringBuffer buff = new StringBuffer();
+ for (long id : this.keySet())
+ {
+ buff.append(helper.unpack(new Identifier(id)))
+ .append("\n");
+ Set<Long> nei = this.get(id);
+ for (long nid : nei)
+ {
+ buff.append(" " + helper.unpack(new Identifier(nid)))
+ .append("\n");
+ }
+ }
+ return buff.toString();
+ }
+ }
+
+ private NeighborMap neighborMap = null;
+
+ HPSEcal(Element node) throws JDOMException
+ {
+ super(node);
+
+ Element layout = node.getChild("layout");
+
+ nx = layout.getAttribute("nx").getIntValue();
+ ny = layout.getAttribute("ny").getIntValue();
+ beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ dface = layout.getAttribute("dface").getDoubleValue();
+
+ if (nx % 2 != 0)
+ oddX = true;
+ }
+
+ public double distanceToFace()
+ {
+ return dface;
+ }
+
+ public double beamGap()
+ {
+ return beamgap;
+ }
+
+ /**
+ * The number of crystals in X in one section.
+ * @return
+ */
+ public double nx()
+ {
+ return nx;
+ }
+
+ /**
+ * The number of crystals in y in one section.
+ * @return
+ */
+ public double ny()
+ {
+ return ny;
+ }
+
+ // Class for storing neighbor incides in XY and side.
+ static class XYSide implements Comparator<XYSide>
+ {
+ int x;
+ int y;
+ int side;
+
+ public XYSide(int x, int y, int side)
+ {
+ this.x = x;
+ this.y = y;
+ this.side = side;
+ }
+
+ public int x()
+ {
+ return x;
+ }
+
+ public int y()
+ {
+ return y;
+ }
+
+ public int side()
+ {
+ return side;
+ }
+
+ public boolean equals(Object o)
+ {
+ XYSide xy = (XYSide)o;
+ return xy.x() == x && xy.y() == y && xy.side() == side;
+ }
+
+ public int compare(XYSide o1, XYSide o2)
+ {
+ if (o1.equals(o2))
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * Get the neighbors for a given cell ID. Each crystal not on an edge
+ * has 8 neighbors. Edge crystals have fewer.
+ * @param id The cell ID.
+ * @return A <code>Set</code> containing the cell's neighbors.
+ */
+ Set<Long> getNeighbors(Long id)
+ {
+ // Get the IDDecoder.
+ IDDecoder dec = getIDDecoder();
+
+ // Set the ID.
+ dec.setID(id);
+
+ // Get ID field values.
+ int x = dec.getValue("ix");
+ int y = dec.getValue("iy");
+ int side = dec.getValue("side");
+
+ // Get field indices.
+ int ix = dec.getFieldIndex("ix");
+ int iy = dec.getFieldIndex("iy");
+ int iside = dec.getFieldIndex("side");
+
+ // Get X, Y, & side neighbor data for this crystal.
+ Set<XYSide> neighbors = getNeighbors(x, y, side);
+
+ // Get buffer with values from current ID.
+ int[] buffer = new int[dec.getFieldCount()];
+ dec.getValues(buffer);
+
+ // Create an encoder to make neighbor IDs.
+ IDEncoder enc = new IDEncoder(dec.getIDDescription());
+
+ // Set to hold neighbor IDs.
+ Set<Long> ids = new HashSet<Long>();
+
+ // Loop over neighbor objects to make IDs.
+ for (XYSide xyside : neighbors)
+ {
+ buffer[ix] = xyside.x;
+ buffer[iy] = xyside.y;
+ buffer[iside] = xyside.side;
+ long nId = enc.setValues(buffer);
+ ids.add(nId);
+ }
+
+ return ids;
+ }
+
+ Set<XYSide> getNeighbors(int ix, int iy, int side)
+ {
+ Set<Integer> xneighbors = getXNeighbors(ix);
+ Set<Integer> yneighbors = getYNeighbors(iy);
+
+ Set<XYSide> neighbors = new HashSet<XYSide>();
+
+ for (Integer jx : xneighbors)
+ {
+ for (Integer jy : yneighbors)
+ {
+ // Filter out self.
+ if (jx == ix && jy == iy)
+ {
+ continue;
+ }
+
+ neighbors.add(new XYSide(jx,jy,side));
+ }
+ }
+
+ return neighbors;
+ }
+
+ Set<Integer> getXNeighbors(int ix)
+ {
+ Set<Integer> neighbors = new HashSet<Integer>();
+
+ // Add self.
+ neighbors.add(ix);
+
+ // Left neighbor.
+ if (isValidX(ix - 1))
+ {
+ neighbors.add(ix - 1);
+ }
+ else if (isValidX(ix - 2))
+ {
+ neighbors.add(ix - 2);
+ }
+
+ // Right neighbor.
+ if (isValidX(ix + 1))
+ {
+ neighbors.add(ix + 1);
+ }
+ else if (isValidX(ix + 2))
+ {
+ neighbors.add(ix + 2);
+ }
+
+ return neighbors;
+ }
+
+ Set<Integer> getYNeighbors(int iy)
+ {
+ Set<Integer> neighbors = new HashSet<Integer>();
+
+ // Add self.
+ neighbors.add(iy);
+
+ // Lower neighbor.
+ if (isValidY(iy - 1))
+ {
+ neighbors.add(iy - 1);
+ }
+ // Upper neighbor.
+ if (isValidY(iy + 1))
+ {
+ neighbors.add(iy + 1);
+ }
+
+ return neighbors;
+ }
+
+ boolean isValidY(int iy)
+ {
+ // Zero is not valid because ID scheme goes from 1.
+ return iy > 0 && iy <= ny;
+ }
+
+ boolean isValidX(int ix)
+ {
+ // Even case.
+ if (!oddX)
+ {
+ return ix >= -nx/2 && ix <= nx/2 && ix != 0;
+ }
+ // Odd case.
+ else
+ {
+ return ix >= (-nx-1)/2 && ix <= (nx+1)/2;
+ }
+ }
+
+ /**
+ * Create a map of crystal IDs to the <code>Set</code> of neighbor crystal IDs.
+ * @return A map of neighbors for each crystal ID.
+ */
+ public NeighborMap getNeighborMap()
+ {
+ if (neighborMap != null)
+ {
+ return neighborMap;
+ }
+
+ // Setup the private instance of the map.
+ neighborMap = new NeighborMap(this.getDetectorElement().getIdentifierHelper());
+
+ IDDecoder dec = getIDDecoder();
+ IDEncoder enc = new IDEncoder(dec.getIDDescription());
+
+ int nfields = dec.getFieldCount();
+ int[] vals = new int[nfields];
+
+ vals[dec.getFieldIndex("system")] = getSystemID();
+
+ int idxx = dec.getFieldIndex("ix");
+ int idxy = dec.getFieldIndex("iy");
+
+ int hnx = nx;
+
+ // Calculate number of X for loop. (from LCDD conv)
+ if (oddX)
+ {
+ hnx -= 1;
+ hnx /= 2;
+ }
+ else
+ {
+ hnx /= 2;
+ }
+
+ for (int side=-1; side <=1; side++)
+ {
+ if (side == 0) continue;
+ vals[dec.getFieldIndex("side")] = side;
+ // Loop over y.
+ for (int iy=1; iy<=ny; iy++)
+ {
+ // Loop over x.
+ for (int ix=0; ix<=hnx; ix++)
+ {
+ // Loop for positive and negative x.
+ for (int j=-1; j<=1; j++)
+ {
+ if (j == 0)
+ continue;
+
+ vals[idxx] = ix*j;
+ vals[idxy] = iy;
+
+ Long id = enc.setValues(vals);
+ Set<Long> neighbors = getNeighbors(id);
+
+ neighborMap.put(id, neighbors);
+ }
+ }
+ }
+ }
+
+ return neighborMap;
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal2.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal2.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal2.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,12 @@
+package org.lcsim.geometry.subdetector;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+
+public class HPSEcal2 extends HPSEcal
+{
+ HPSEcal2(Element node) throws JDOMException
+ {
+ super(node);
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal3.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal3.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSEcal3.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,387 @@
+package org.lcsim.geometry.subdetector;
+
+import hep.graphics.heprep.HepRep;
+import hep.graphics.heprep.HepRepFactory;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.converter.heprep.DetectorElementToHepRepConverter;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.util.IDEncoder;
+
+/**
+ * Reconstruction version of HPS ECal with crystal array.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Timothy Nelson <[log in to unmask]>
+ * @version $Id: HPSEcal3.java,v 1.3 2012/04/30 18:04:38 jeremy Exp $
+ */
+public class HPSEcal3 extends AbstractSubdetector {
+ private int nx;
+ private int ny;
+ //private double beamgap;
+ //private double dface;
+ private boolean oddX;
+ List<CrystalRange> removeCrystals = new ArrayList<CrystalRange>();
+
+ public static class NeighborMap extends HashMap<Long, Set<Long>> {
+ IIdentifierHelper helper;
+
+ public NeighborMap(IIdentifierHelper helper) {
+ this.helper = helper;
+ }
+
+ public String toString() {
+ System.out.println("NeighborMap has " + this.size() + " entries.");
+ StringBuffer buff = new StringBuffer();
+ for (long id : this.keySet()) {
+ buff.append(helper.unpack(new Identifier(id))).append("\n");
+ Set<Long> nei = this.get(id);
+ for (long nid : nei) {
+ buff.append(" " + helper.unpack(new Identifier(nid))).append("\n");
+ }
+ }
+ return buff.toString();
+ }
+ }
+
+ private NeighborMap neighborMap = null;
+
+ HPSEcal3(Element node) throws JDOMException {
+ super(node);
+
+ Element layout = node.getChild("layout");
+
+ nx = layout.getAttribute("nx").getIntValue();
+ ny = layout.getAttribute("ny").getIntValue();
+ //beamgap = layout.getAttribute("beamgap").getDoubleValue();
+ //dface = layout.getAttribute("dface").getDoubleValue();
+
+ if (nx % 2 != 0)
+ oddX = true;
+
+ // Setup range of indices to be skipped.
+ for (Object obj : layout.getChildren("remove")) {
+ Element remove = (Element) obj;
+ try {
+ removeCrystals.add(new CrystalRange(remove));
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ /*
+ * <remove ixmin="2" ixmax="10" iymin="-1" iymax="1"/>
+ */
+ }
+
+ private static class CrystalRange {
+ int ixmin;
+ int ixmax;
+ int iymin;
+ int iymax;
+
+ CrystalRange(Element elem) throws Exception {
+ ixmin = ixmax = iymin = iymax = 0;
+
+ if (elem.getAttribute("ixmin") != null) {
+ ixmin = elem.getAttribute("ixmin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmin parameter.");
+ }
+
+ if (elem.getAttribute("ixmax") != null) {
+ ixmax = elem.getAttribute("ixmax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymin") != null) {
+ iymin = elem.getAttribute("iymin").getIntValue();
+ } else {
+ throw new RuntimeException("Missing ixmax parameter.");
+ }
+
+ if (elem.getAttribute("iymax") != null) {
+ iymax = elem.getAttribute("iymax").getIntValue();
+ } else {
+ throw new RuntimeException("Missing iymax parameter.");
+ }
+ }
+ }
+
+ private boolean isValidXY(int ix, int iy) {
+ if (!isValidX(ix))
+ return false;
+ if (!isValidY(iy))
+ return false;
+ return checkRange(ix, iy, this.removeCrystals);
+ }
+
+ private boolean checkRange(int ix, int iy, List<CrystalRange> ranges) {
+ if (ranges.size() == 0)
+ return true;
+ for (CrystalRange range : ranges) {
+ if ((ix >= range.ixmin && ix <= range.ixmax) && ((iy >= range.iymin) && (iy <= range.iymax))) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ //public double distanceToFace() {
+ // return dface;
+ //}
+
+ //public double beamGap() {
+ // return beamgap;
+ //}
+
+ /**
+ * The number of crystals in X in one section.
+ *
+ * @return
+ */
+ public double nx() {
+ return nx;
+ }
+
+ /**
+ * The number of crystals in y in one section.
+ *
+ * @return
+ */
+ public double ny() {
+ return ny;
+ }
+
+ // Class for storing neighbor indices in XY and side.
+ static class XY implements Comparator<XY> {
+ int x;
+ int y;
+
+ public XY(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int x() {
+ return x;
+ }
+
+ public int y() {
+ return y;
+ }
+
+ public boolean equals(Object o) {
+ XY xy = (XY) o;
+ return xy.x() == x && xy.y() == y;
+ }
+
+ public int compare(XY o1, XY o2) {
+ if (o1.equals(o2)) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * Get the neighbors for a given cell ID. Each crystal not on an edge has 8 neighbors. Edge crystals have fewer.
+ * @param id The cell ID.
+ * @return A <code>Set</code> containing the cell's neighbors.
+ */
+ Set<Long> getNeighbors(Long id) {
+ // Get the IDDecoder.
+ IDDecoder dec = getIDDecoder();
+
+ // Set the ID.
+ dec.setID(id);
+
+ // Get ID field values.
+ int x = dec.getValue("ix");
+ int y = dec.getValue("iy");
+
+ // Get field indices.
+ int ix = dec.getFieldIndex("ix");
+ int iy = dec.getFieldIndex("iy");
+
+ // Get X, Y, & side neighbor data for this crystal.
+ Set<XY> neighbors = getNeighbors(x, y);
+
+ // Get buffer with values from current ID.
+ int[] buffer = new int[dec.getFieldCount()];
+ dec.getValues(buffer);
+
+ // Create an encoder to make neighbor IDs.
+ IDEncoder enc = new IDEncoder(dec.getIDDescription());
+
+ // Set to hold neighbor IDs.
+ Set<Long> ids = new HashSet<Long>();
+
+ // Loop over neighbor objects to make IDs.
+ for (XY xyside : neighbors) {
+ buffer[ix] = xyside.x;
+ buffer[iy] = xyside.y;
+ long nId = enc.setValues(buffer);
+ ids.add(nId);
+ }
+
+ return ids;
+ }
+
+ Set<XY> getNeighbors(int ix, int iy) {
+ Set<Integer> xneighbors = getXNeighbors(ix);
+ Set<Integer> yneighbors = getYNeighbors(iy);
+
+ Set<XY> neighbors = new HashSet<XY>();
+
+ for (Integer jx : xneighbors) {
+ for (Integer jy : yneighbors) {
+ // Filter out self.
+ if (jx == ix && jy == iy) {
+ continue;
+ }
+
+ // Check for valid neighbor.
+ // FIXME: Duplication of isValidX + isValidY.
+ if (!isValidXY(jx, jy))
+ continue;
+
+ neighbors.add(new XY(jx, jy));
+ }
+ }
+
+ return neighbors;
+ }
+
+ Set<Integer> getXNeighbors(int ix) {
+ Set<Integer> neighbors = new HashSet<Integer>();
+
+ // Add self.
+ neighbors.add(ix);
+
+ // Left neighbor.
+ if (isValidX(ix - 1)) {
+ neighbors.add(ix - 1);
+ } else if (isValidX(ix - 2)) {
+ neighbors.add(ix - 2);
+ }
+
+ // Right neighbor.
+ if (isValidX(ix + 1)) {
+ neighbors.add(ix + 1);
+ } else if (isValidX(ix + 2)) {
+ neighbors.add(ix + 2);
+ }
+
+ return neighbors;
+ }
+
+ Set<Integer> getYNeighbors(int iy) {
+ Set<Integer> neighbors = new HashSet<Integer>();
+
+ // Add self.
+ neighbors.add(iy);
+
+ // Lower neighbor.
+ if (isValidY(iy - 1)) {
+ neighbors.add(iy - 1);
+ }
+
+ // Upper neighbor.
+ if (isValidY(iy + 1)) {
+ neighbors.add(iy + 1);
+ }
+
+ return neighbors;
+ }
+
+ boolean isValidY(int iy) {
+ // Zero is not valid because ID scheme goes from 1.
+ return iy >= -ny && iy <= ny && iy != 0;
+ }
+
+ boolean isValidX(int ix) {
+ // Even case.
+ if (!oddX) {
+ return ix >= -nx / 2 && ix <= nx / 2 && ix != 0;
+ }
+ // Odd case.
+ else {
+ return ix >= (-nx - 1) / 2 && ix <= (nx + 1) / 2;
+ }
+ }
+
+ /**
+ * Create a map of crystal IDs to the <code>Set</code> of neighbor crystal IDs.
+ *
+ * @return A map of neighbors for each crystal ID.
+ */
+ public NeighborMap getNeighborMap() {
+ if (neighborMap != null) {
+ return neighborMap;
+ }
+
+ // Setup the private instance of the map.
+ neighborMap = new NeighborMap(this.getDetectorElement().getIdentifierHelper());
+
+ IDDecoder dec = getIDDecoder();
+ IDEncoder enc = new IDEncoder(dec.getIDDescription());
+
+ int nfields = dec.getFieldCount();
+ int[] vals = new int[nfields];
+
+ vals[dec.getFieldIndex("system")] = getSystemID();
+
+ int idxx = dec.getFieldIndex("ix");
+ int idxy = dec.getFieldIndex("iy");
+
+ /*
+ int hnx = nx;
+
+ // Calculate number of X for loop. (from LCDD conv)
+ if (oddX) {
+ hnx -= 1;
+ hnx /= 2;
+ } else {
+ hnx /= 2;
+ }
+ */
+
+ // Loop over y.
+ for (int iy = -ny; iy <= ny; iy++) {
+ int loopx = (int) Math.floor(nx / 2);
+ // Loop over x.
+ for (int ix = -loopx; ix <= loopx; ix++) {
+ if (!isValidXY(ix, iy))
+ continue;
+
+ vals[idxx] = ix;
+ vals[idxy] = iy;
+
+ Long id = enc.setValues(vals);
+ Set<Long> neighbors = getNeighbors(id);
+
+ neighborMap.put(id, neighbors);
+ }
+ }
+
+ return neighborMap;
+ }
+
+ public void appendHepRep(HepRepFactory factory, HepRep heprep) {
+ DetectorElementToHepRepConverter.convert(getDetectorElement(), factory, heprep, -1, false, getVisAttributes().getColor());
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSMuonCalorimeter.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSMuonCalorimeter.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSMuonCalorimeter.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,31 @@
+package org.lcsim.geometry.subdetector;
+
+import hep.graphics.heprep.HepRep;
+import hep.graphics.heprep.HepRepFactory;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.converter.heprep.DetectorElementToHepRepConverter;
+
+/**
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @version $Id: HPSMuonCalorimeter.java,v 1.2 2013/01/25 00:13:14 jeremy Exp $
+ */
+public class HPSMuonCalorimeter extends AbstractSubdetector
+{
+ HPSMuonCalorimeter(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ public void appendHepRep(HepRepFactory factory, HepRep heprep)
+ {
+ DetectorElementToHepRepConverter.convert(
+ getDetectorElement(),
+ factory,
+ heprep,
+ -1,
+ false,
+ getVisAttributes().getColor());
+ }
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,32 @@
+package org.lcsim.geometry.subdetector;
+
+import hep.graphics.heprep.HepRep;
+import hep.graphics.heprep.HepRepFactory;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.converter.heprep.DetectorElementToHepRepConverter;
+
+public class HPSTracker extends AbstractTracker
+{
+ HPSTracker(Element node) throws JDOMException
+ {
+ super(node);
+ }
+
+ public void appendHepRep(HepRepFactory factory, HepRep heprep)
+ {
+ DetectorElementToHepRepConverter.convert(getDetectorElement(), factory, heprep, -1, false, getVisAttributes().getColor());
+ }
+
+ public boolean isEndcap()
+ {
+ return false;
+ }
+
+ public boolean isBarrel()
+ {
+ return true;
+ }
+
+}
Added: java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker2.java
=============================================================================
--- java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker2.java (added)
+++ java/trunk/detector-model/src/main/java/org/lcsim/geometry/subdetector/HPSTracker2.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,27 @@
+package org.lcsim.geometry.subdetector;
+
+import hep.graphics.heprep.HepRep;
+import hep.graphics.heprep.HepRepFactory;
+
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.lcsim.detector.converter.heprep.DetectorElementToHepRepConverter;
+
+public class HPSTracker2 extends AbstractTracker {
+
+ HPSTracker2(Element node) throws JDOMException {
+ super(node);
+ }
+
+ public void appendHepRep(HepRepFactory factory, HepRep heprep) {
+ DetectorElementToHepRepConverter.convert(getDetectorElement(), factory, heprep, -1, false, getVisAttributes().getColor());
+ }
+
+ public boolean isEndcap() {
+ return false;
+ }
+
+ public boolean isBarrel() {
+ return true;
+ }
+}
Copied: java/trunk/detector-model/src/test/java/org/hps/detector/svt/SvtDetectorSetupTest.java (from r3746, java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java)
=============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/SvtDetectorSetupTest.java (original)
+++ java/trunk/detector-model/src/test/java/org/hps/detector/svt/SvtDetectorSetupTest.java Tue Oct 6 11:36:11 2015
@@ -1,10 +1,12 @@
-package org.hps.conditions.svt;
+package org.hps.detector.svt;
import java.util.List;
+import java.util.logging.Logger;
import junit.framework.TestCase;
import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.svt.SvtConditions;
import org.lcsim.detector.tracker.silicon.HpsSiSensor;
import org.lcsim.geometry.Detector;
@@ -17,7 +19,7 @@
*/
// TODO: Update this test with more meaningful assertions.
public final class SvtDetectorSetupTest extends TestCase {
-
+
/**
* Maximum channel number.
*/
@@ -60,6 +62,7 @@
public void test() throws Exception {
final DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+ conditionsManager.addConditionsListener(new SvtDetectorSetup());
conditionsManager.setDetector("HPS-Proposal2014-v7-2pt2", 0);
// Get the detector.
Copied: java/trunk/detector-model/src/test/java/org/hps/detector/svt/TestRunSvtDetectorSetupTest.java (from r3746, java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java)
=============================================================================
--- java/trunk/conditions/src/test/java/org/hps/conditions/svt/TestRunSvtDetectorSetupTest.java (original)
+++ java/trunk/detector-model/src/test/java/org/hps/detector/svt/TestRunSvtDetectorSetupTest.java Tue Oct 6 11:36:11 2015
@@ -1,10 +1,11 @@
-package org.hps.conditions.svt;
+package org.hps.detector.svt;
import java.util.List;
import junit.framework.TestCase;
import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.svt.TestRunSvtConditions;
import org.lcsim.detector.tracker.silicon.HpsTestRunSiSensor;
import org.lcsim.geometry.Detector;
Added: java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java
=============================================================================
--- java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java (added)
+++ java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSEcalAPITest.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,74 @@
+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 {
+
+ final GeometryReader geometryReader = new GeometryReader();
+ final InputStream in = this.getClass().getResourceAsStream("/org/lcsim/geometry/subdetector/HPSEcal3Test.xml");
+ final Detector detector = geometryReader.read(in);
+
+ final HPSEcalDetectorElement ecal = (HPSEcalDetectorElement) detector.getSubdetector("Ecal")
+ .getDetectorElement();
+
+ final HPSEcalAPI api = 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 (final Integer yIndex : api.getYIndices()) {
+ if (yIndex == 0) {
+ System.out.println("skipping yIndex = 0");
+ continue;
+ }
+ for (final 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;
+ }
+ final EcalCrystal crystal = api.getCrystal(xIndex, yIndex);
+ assertNotNull("Failed to find crystal at ix = " + xIndex + ", iy = " + yIndex, crystal);
+ }
+ }
+
+ for (final Integer yIndex : api.getYIndices()) {
+ final 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 (final Integer xIndex : api.getXIndices()) {
+ final 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());
+ }
+ }
+ }
+}
Added: java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterTest.java
=============================================================================
--- java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterTest.java (added)
+++ java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSMuonCalorimeterTest.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,48 @@
+package org.lcsim.detector.converter.compact;
+
+import java.io.InputStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.GeometryReader;
+
+public class HPSMuonCalorimeterTest extends TestCase
+{
+
+ Detector detector = null;
+ private static final String resource = "/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml";
+
+ public static Test suite()
+ {
+ return new TestSuite(HPSMuonCalorimeterTest.class);
+ }
+
+ public void setUp()
+ {
+ InputStream in = this.getClass().getResourceAsStream(resource);
+ GeometryReader reader = new GeometryReader();
+ try {
+ detector = reader.read(in);
+ } catch (Throwable x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ public void testMuon()
+ {
+ IDetectorElement de = detector.getSubdetector("MUON").getDetectorElement();
+ System.out.println("MUON has " + de.getChildren().size() + " children.");
+ IIdentifierHelper helper = de.getIdentifierHelper();
+ IIdentifierDictionary dict = helper.getIdentifierDictionary();
+ System.out.println(dict.toString());
+ for (IDetectorElement child : de.getChildren()) {
+ System.out.println(child.getName() + " => " + helper.unpack(child.getIdentifier()));
+ }
+ }
+}
Added: java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSTracker2ConverterTest.java
=============================================================================
--- java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSTracker2ConverterTest.java (added)
+++ java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HPSTracker2ConverterTest.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,117 @@
+package org.lcsim.detector.converter.compact;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.lcsim.detector.converter.compact.subdetector.HpsTracker2;
+import org.lcsim.detector.converter.compact.subdetector.SvtStereoLayer;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.GeometryReader;
+import org.lcsim.util.log.DefaultLogFormatter;
+import org.lcsim.util.log.LogUtil;
+
+/**
+ * Unit test for the HPSTracker2Coverter.
+ *
+ * @author Jeremy McCormick <[log in to unmask]>
+ * @author Omar Moreno <[log in to unmask]>
+ */
+public class HPSTracker2ConverterTest extends TestCase {
+
+ // Initialize the logger
+ private static Logger logger = LogUtil.create(HPSTracker2Converter.class.getName(),
+ new DefaultLogFormatter(), Level.INFO);
+
+ Detector detector = null;
+
+ //-----------------//
+ //--- Constants ---//
+ //-----------------//
+
+ private static final int TOTAL_NUMBER_OF_SENSORS = 20;
+ private static final int TOTAL_NUMBER_OF_STEREO_LAYERS = 10;
+ private static final String SUBDETECTOR_NAME = "Tracker";
+
+ public static final int NUMBER_OF_READOUT_STRIPS = 639;
+ public static final int NUMBER_OF_SENSE_STRIPS = 1277;
+
+ //-----------------//
+ //-----------------//
+
+ public static Test suite() {
+ return new TestSuite(HPSTracker2ConverterTest.class);
+ }
+
+ private static final String resource = "/org/lcsim/geometry/subdetector/HPSTracker2Test.xml";
+ public void setUp() {
+ InputStream in = this.getClass().getResourceAsStream(resource);
+
+ GeometryReader reader = new GeometryReader();
+
+ try {
+ detector = reader.read(in);
+ }
+ catch (Throwable x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+ public void testHPSTracker2Converter() {
+
+ // Test if the correct number of sensors was created.
+ logger.info("Checking if the correct number of sensors were created.");
+ List<HpsSiSensor> sensors = detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement().findDescendants(HpsSiSensor.class);
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: The wrong number of sensors were created.",
+ sensors.size() == TOTAL_NUMBER_OF_SENSORS);
+ logger.info("Total number of sensors that were created: " + sensors.size());
+
+ // Test if the sensors that were created are instances of HpsSiSensor
+ logger.info("Checking if sensors were initialized correctly");
+ for(HpsSiSensor sensor : sensors) {
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Sensor is of wrong type: " + sensor.getClass().getSimpleName(),
+ sensor instanceof HpsSiSensor);
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Wrong number of readout electrodes found.",
+ sensor.getReadoutElectrodes(ChargeCarrier.HOLE).getNCells() == NUMBER_OF_READOUT_STRIPS);
+
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Wrong number of sense electrodes found.",
+ sensor.getSenseElectrodes(ChargeCarrier.HOLE).getNCells() == NUMBER_OF_SENSE_STRIPS);
+ logger.info(sensor.toString());
+ }
+ logger.info("Sensors were all initialized correctly.");
+
+ // Check that the correct number of stereo layers were created
+ logger.info("Checking if the correct number of stereo layers were created.");
+ List<SvtStereoLayer> stereoLayers = ((HpsTracker2) detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement()).getStereoPairs();
+ // Check that the number of stereo layers created is as expected
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: The wrong number of stereo layers were created.",
+ stereoLayers.size() == TOTAL_NUMBER_OF_STEREO_LAYERS);
+ logger.info("Total number of stereo layers created: " + stereoLayers.size());
+
+ for(SvtStereoLayer stereoLayer : stereoLayers){
+ logger.fine(stereoLayer.toString());
+
+ // The sensors comprising the stereo layer should belong to the same detector volume
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Sensors belong to different detector volumes.",
+ stereoLayer.getAxialSensor().getModuleNumber() == stereoLayer.getStereoSensor().getModuleNumber());
+
+ // If the stereo layer is part of the top detector volume, the axial layers have an odd layer number.
+ // If the stereo layer is part of the bottom detector volume, the axial layers have an even layer number.
+ logger.info("Checking if the layers are oriented correctly.");
+ if(stereoLayer.getAxialSensor().isTopLayer()){
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Sensors composing the stereo layer are flipped",
+ stereoLayer.getAxialSensor().getLayerNumber()%2 == 1);
+ } else {
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Sensors composing the stereo layer are flipped",
+ stereoLayer.getAxialSensor().getLayerNumber()%2 == 0);
+ }
+ }
+ }
+}
Added: java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HpsTestRunSiSensorConverterTest.java
=============================================================================
--- java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HpsTestRunSiSensorConverterTest.java (added)
+++ java/trunk/detector-model/src/test/java/org/lcsim/detector/converter/compact/HpsTestRunSiSensorConverterTest.java Tue Oct 6 11:36:11 2015
@@ -0,0 +1,95 @@
+package org.lcsim.detector.converter.compact;
+
+import java.io.InputStream;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.lcsim.detector.converter.compact.subdetector.HpsTracker2;
+import org.lcsim.detector.converter.compact.subdetector.SvtStereoLayer;
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
+import org.lcsim.detector.tracker.silicon.HpsTestRunSiSensor;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.GeometryReader;
+
+/**
+ * Unit test for the {@link HPSTracker2Converter} when the sensor type
+ * is equal to {@link HpsTestRunSiSensor}
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ */
+public class HpsTestRunSiSensorConverterTest extends TestCase {
+
+ Detector detector = null;
+
+ //-----------------//
+ //--- Constants ---//
+ //-----------------//
+ private static final int TOTAL_NUMBER_OF_SENSORS = 20;
+ private static final int TOTAL_NUMBER_OF_STEREO_LAYERS = 10;
+ private static final String SUBDETECTOR_NAME = "Tracker";
+ private static final String RESOURCE = "/org/lcsim/geometry/subdetector/HpsTestRunSiSensorConverterTest.xml";
+
+ /*public static Test suite() {
+ return new TestSuite(HPSTracker2ConverterTest.class);
+ }*/
+
+ public void setUp() {
+
+ InputStream in = this.getClass().getResourceAsStream(RESOURCE);
+
+ GeometryReader reader = new GeometryReader();
+
+ try {
+ detector = reader.read(in);
+ }
+ catch (Throwable x) {
+ throw new RuntimeException(x);
+ }
+ }
+
+
+ public void testHPSTracker2Converter() {
+
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: Checking if the correct number of sensors were created.");
+ List<HpsSiSensor> sensors = detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement().findDescendants(HpsSiSensor.class);
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: The wrong number of sensors were created.", sensors.size() == TOTAL_NUMBER_OF_SENSORS);
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: Total number of sensors that were created: " + sensors.size());
+
+
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: Checking if sensor is instance of HpsTestRunSiSensor.");
+ for(HpsSiSensor sensor : sensors) {
+ assertTrue("[ " + this.getClass().getSimpleName() + " ]: Sensor is of wrong type: " + sensor.getClass().getSimpleName(),
+ sensor instanceof HpsTestRunSiSensor);
+ }
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: Sensors are all instances of HpsTestRunSiSensor.");
+
+
+ // Check that the correct number of stereo layers were created
+ System.out.println("[ HPSTracker2ConverterTest ]: Checking if the correct number of stereo layers were created.");
+ List<SvtStereoLayer> stereoLayers = ((HpsTracker2) detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement()).getStereoPairs();
+ // Check that the number of stereo layers created is as expected
+ assertTrue("The wrong number of stereo layers were created.", stereoLayers.size() == TOTAL_NUMBER_OF_STEREO_LAYERS);
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: Total number of stereo layers created: " + stereoLayers.size());
+
+ for(SvtStereoLayer stereoLayer : stereoLayers){
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: " + stereoLayer.toString());
+
+ // The sensors comprising the stereo layer should belong to the same detector volume
+ assertTrue("Sensors belong to different detector volumes.",
+ stereoLayer.getAxialSensor().getModuleNumber() == stereoLayer.getStereoSensor().getModuleNumber());
+
+ // If the stereo layer is part of the top detector volume, the axial layers have an odd layer number.
+ // If the stereo layer is part of the bottom detector volumen, the axial layers have an even layer number.
+ System.out.println("[ " + this.getClass().getSimpleName() + " ]: check if the layers are oriented correctly.");
+ if(stereoLayer.getAxialSensor().isTopLayer()){
+ assertTrue("Sensors composing the stereo layer are flipped", stereoLayer.getAxialSensor().getLayerNumber()%2 == 1);
+ } else {
+ assertTrue("Sensors composing the stereo layer are flipped", stereoLayer.getAxialSensor().getLayerNumber()%2 == 0);
+
+ }
+ }
+ }
+}
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcal3Test.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,56 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+ <info name="HPSEcal3Test" />
+ <define>
+ <!-- world volume -->
+ <constant name="world_side" value="10000.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="200.0*cm" />
+ <constant name="tracking_region_min" value="5.0*cm" />
+ <constant name="tracking_region_zmax" value="100.0*cm" />
+ <!-- ECal placement parameters -->
+ <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">
+ <D value="8.28" unit="g/cm3" />
+ <composite n="1" ref="Pb" />
+ <composite n="1" ref="W" />
+ <composite n="4" ref="O" />
+ </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" />
+ <layout beamgapBottom="40.0*mm" beamgapTop="20.0*mm" nx="46" ny="5" dface="120.0*cm">
+ <remove ixmin="2" ixmax="7" iymin="-1" iymax="1" />
+ </layout>
+ </detector>
+ -->
+ </detectors>
+ <readouts>
+ <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>
+ </readouts>
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcalTest.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcalTest.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSEcalTest.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,57 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPSEcalTest">
+ <comment>Test of class org.lcsim.geometry.compact.converter.lcdd.TestBeamCalorimeter</comment>
+ </info>
+
+ <define>
+
+ <!-- world -->
+ <constant name="world_side" value="30000" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="150.0*cm"/>
+ <constant name="tracking_region_zmax" value="200.0*cm"/>
+
+ </define>
+
+ <materials>
+ </materials>
+
+ <detectors>
+
+ <detector id="1"
+ name="HPSEcalTest"
+ type="HPSEcal"
+ insideTrackingVolume="false">
+ <!-- stuff goes here -->
+ </detector>
+ </detectors>
+
+<!--
+ readout="CalHits"
+-->
+
+ <readouts>
+<!--
+ <readout name="CalHits">
+ <segmentation type="GridXYZ" gridSizeX="10.0" gridSizeY="10.0" />
+ <id>system:3,barrel:2,layer:7,x:32:-16,y:-16</id>
+ </readout>
+-->
+ </readouts>
+ <fields>
+<!--
+ <field type="Solenoid" name="GlobalSolenoid"
+ inner_field="5.0"
+ outer_field="-0.6"
+ zmax="1000"
+ outer_radius="(221.0+ 5.0 + 17.5 + 40./2.)*cm"/>
+-->
+ </fields>
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeter2Test.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeter2Test.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeter2Test.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,57 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPSMuonCalorimeter2Test" />
+
+ <define>
+
+ <!-- world volume -->
+ <constant name="world_side" value="10000.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="5.0*cm" />
+ <constant name="tracking_region_min" value="0.0*cm" />
+ <constant name="tracking_region_zmax" value="100.0*cm" />
+
+ </define>
+
+ <materials>
+ <material name="Scintillator">
+ <D value="1.032" unit="g/cm3"/>
+ <composite n="9" ref="C"/>
+ <composite n="10" ref="H"/>
+ </material>
+ </materials>
+
+ <detectors>
+ <detector id="2" name="MUON" type="HPSMuonCalorimeter2" insideTrackingVolume="false" readout="MUON_HITS">
+ <parameters front_face_to_target="177.0*cm"
+ dead_zone_angle="0.015"
+ strip_thickness="1.0*cm"
+ strip_spacing_z="1.0"
+ strip_spacing_y="0.1"
+ strip_spacing_x="0.1"
+ strip_spacing_z_outer="1.0*cm"
+ center_x="0." />
+
+ <layer id="1">
+ <slice material="Iron" sensitive="false" thickness="30.0*cm" />
+ <slice material="Scintillator" sensitive="true" />
+ <slice material="Scintillator" sensitive="true" />
+ </layer>
+
+ </detector>
+ </detectors>
+
+ <readouts>
+ <readout name="MUON_HITS">
+ <segmentation type="GridXYZ" gridSizeX="5.0" gridSizeY="5.0" gridSizeZ="0.0" />
+ <id>system:6,side:-2,layer:4,slice:3,x:32:-8,y:-6</id>
+ </readout>
+ </readouts>
+
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSMuonCalorimeterTest.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,151 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPSMuonCalorimeterTest" />
+
+ <define>
+
+ <!-- world volume -->
+ <constant name="world_side" value="10000.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="5.0*cm" />
+ <constant name="tracking_region_min" value="0.0*cm" />
+ <constant name="tracking_region_zmax" value="100.0*cm" />
+
+ <!-- muon parameters -->
+ <!--<constant name="beam_gap" value="22.785 + 1.0" />-->
+ <constant name="beam_gap" value="33.0" />
+ <constant name="muon_abs_z" value="150.0" />
+ <constant name="muon_sens_z" value="10.0" />
+ <constant name="muon_strip_gap" value="1.0" />
+
+ <!-- muon layer 1 -->
+
+ <constant name="muon_abs1_x" value="1182.0" />
+ <constant name="muon_abs1_y" value="131.4" />
+ <constant name="muon_abs1_z" value="300.0" />
+ <constant name="muon_abs1_pz" value="1920.0" />
+ <constant name="muon_abs1_py" value="beam_gap + muon_abs1_y / 2" />
+
+ <constant name="muon_sens1_x" value="muon_abs1_x" />
+ <constant name="muon_sens1_y" value="muon_abs1_y" />
+ <constant name="muon_sens1_pz" value="muon_abs1_pz + muon_abs1_z / 2 + muon_strip_gap + muon_sens_z / 2" />
+ <constant name="muon_sens1_py" value="beam_gap + muon_sens1_y / 2" />
+
+ <constant name="muon_sens2_x" value="muon_sens1_x" />
+ <constant name="muon_sens2_y" value="muon_sens1_y" />
+ <constant name="muon_sens2_pz" value="muon_sens1_pz + muon_sens_z + muon_strip_gap" />
+ <constant name="muon_sens2_py" value="beam_gap + muon_sens2_y / 2" />
+
+ <!-- muon layer 2 -->
+
+ <constant name="muon_abs2_x" value="1276.0" />
+ <constant name="muon_abs2_y" value="130.72" />
+ <constant name="muon_abs2_pz" value="2168.0" />
+ <constant name="muon_abs2_py" value="beam_gap + muon_abs2_y / 2" />
+
+ <constant name="muon_sens3_x" value="muon_abs2_x" />
+ <constant name="muon_sens3_y" value="muon_abs2_y" />
+ <constant name="muon_sens3_pz" value="muon_abs2_pz + muon_abs_z / 2 + muon_strip_gap + muon_sens_z / 2" />
+ <constant name="muon_sens3_py" value="beam_gap + muon_sens3_y / 2" />
+
+ <constant name="muon_sens4_x" value="muon_sens3_x" />
+ <constant name="muon_sens4_y" value="muon_sens3_y" />
+ <constant name="muon_sens4_pz" value="muon_sens3_pz + muon_sens_z + muon_strip_gap" />
+ <constant name="muon_sens4_py" value="beam_gap + muon_sens4_y / 2" />
+
+ <!-- muon layer 3 -->
+
+ <constant name="muon_abs3_x" value="1406.0" />
+ <constant name="muon_abs3_y" value="140.7" />
+ <constant name="muon_abs3_pz" value="2341.0" />
+ <constant name="muon_abs3_py" value="beam_gap + muon_abs3_y / 2" />
+
+ <constant name="muon_sens5_x" value="muon_abs3_x" />
+ <constant name="muon_sens5_y" value="muon_abs3_y" />
+ <constant name="muon_sens5_pz" value="muon_abs3_pz + muon_abs_z / 2 + muon_strip_gap + muon_sens_z / 2" />
+ <constant name="muon_sens5_py" value="beam_gap + muon_sens5_y / 2" />
+
+ <constant name="muon_sens6_x" value="muon_sens5_x" />
+ <constant name="muon_sens6_y" value="muon_sens5_y" />
+ <constant name="muon_sens6_pz" value="muon_sens5_pz + muon_sens_z + muon_strip_gap" />
+ <constant name="muon_sens6_py" value="beam_gap + muon_sens6_y / 2" />
+
+ <!-- muon layer 4 -->
+
+ <constant name="muon_abs4_x" value="1546.0" />
+ <constant name="muon_abs4_y" value="150.0" />
+ <constant name="muon_abs4_pz" value="2514.0" />
+ <constant name="muon_abs4_py" value="beam_gap + muon_abs4_y / 2" />
+
+ <constant name="muon_sens7_x" value="muon_abs4_x" />
+ <constant name="muon_sens7_y" value="muon_abs4_y" />
+ <constant name="muon_sens7_pz" value="muon_abs4_pz + muon_abs_z / 2 + muon_strip_gap + muon_sens_z / 2" />
+ <constant name="muon_sens7_py" value="beam_gap + muon_sens7_y / 2" />
+
+ <constant name="muon_sens8_x" value="muon_sens7_x" />
+ <constant name="muon_sens8_y" value="muon_sens7_y" />
+ <constant name="muon_sens8_pz" value="muon_sens7_pz + muon_sens_z + muon_strip_gap" />
+ <constant name="muon_sens8_py" value="beam_gap + muon_sens8_y / 2" />
+
+ </define>
+
+ <materials>
+ </materials>
+
+ <detectors>
+ <detector id="2" name="MUON" type="HPSMuonCalorimeter" insideTrackingVolume="false" readout="MUON_HITS">
+ <layer id="1">
+ <!-- nstrips="26" strip_orientation="x" strip_gap="0.01" -->
+ <box x="muon_abs1_x" y="muon_abs1_y" z="muon_abs1_z" py="muon_abs1_py" pz="muon_abs1_pz" material="Steel235" />
+ <box x="muon_abs1_x" y="muon_abs1_y" z="muon_abs1_z" py="-muon_abs1_py" pz="muon_abs1_pz" material="Steel235" />
+ <box x="muon_sens1_x" y="muon_sens1_y" z="muon_sens_z" py="muon_sens1_py" pz="muon_sens1_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens1_x" y="muon_sens1_y" z="muon_sens_z" py="-muon_sens1_py" pz="muon_sens1_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens2_x" y="muon_sens2_y" z="muon_sens_z" py="muon_sens2_py" pz="muon_sens2_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens2_x" y="muon_sens2_y" z="muon_sens_z" py="-muon_sens2_py" pz="muon_sens2_pz" material="Polystyrene" sensitive="true" />
+ </layer>
+ <layer id="2">
+ <box x="muon_abs2_x" y="muon_abs2_y" z="muon_abs_z" py="muon_abs2_py" pz="muon_abs2_pz" material="Steel235" />
+ <box x="muon_abs2_x" y="muon_abs2_y" z="muon_abs_z" py="-muon_abs2_py" pz="muon_abs2_pz" material="Steel235" />
+ <box x="muon_sens3_x" y="muon_sens3_y" z="muon_sens_z" py="muon_sens3_py" pz="muon_sens3_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens3_x" y="muon_sens3_y" z="muon_sens_z" py="-muon_sens3_py" pz="muon_sens3_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens4_x" y="muon_sens4_y" z="muon_sens_z" py="muon_sens4_py" pz="muon_sens4_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens4_x" y="muon_sens4_y" z="muon_sens_z" py="-muon_sens4_py" pz="muon_sens4_pz" material="Polystyrene" sensitive="true" />
+ </layer>
+ <layer id="3">
+ <box x="muon_abs3_x" y="muon_abs3_y" z="muon_abs_z" py="muon_abs3_py" pz="muon_abs3_pz" material="Steel235" />
+ <box x="muon_abs3_x" y="muon_abs3_y" z="muon_abs_z" py="-muon_abs3_py" pz="muon_abs3_pz" material="Steel235" />
+ <box x="muon_sens5_x" y="muon_sens5_y" z="muon_sens_z" py="muon_sens5_py" pz="muon_sens5_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens5_x" y="muon_sens5_y" z="muon_sens_z" py="-muon_sens5_py" pz="muon_sens5_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens6_x" y="muon_sens6_y" z="muon_sens_z" py="muon_sens6_py" pz="muon_sens6_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens6_x" y="muon_sens6_y" z="muon_sens_z" py="-muon_sens6_py" pz="muon_sens6_pz" material="Polystyrene" sensitive="true" />
+ </layer>
+ <layer id="4">
+ <box x="muon_abs4_x" y="muon_abs4_y" z="muon_abs_z" py="muon_abs4_py" pz="muon_abs4_pz" material="Steel235" />
+ <box x="muon_abs4_x" y="muon_abs4_y" z="muon_abs_z" py="-muon_abs4_py" pz="muon_abs4_pz" material="Steel235" />
+ <box x="muon_sens7_x" y="muon_sens7_y" z="muon_sens_z" py="muon_sens7_py" pz="muon_sens7_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens7_x" y="muon_sens7_y" z="muon_sens_z" py="-muon_sens7_py" pz="muon_sens7_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens8_x" y="muon_sens8_y" z="muon_sens_z" py="muon_sens8_py" pz="muon_sens8_pz" material="Polystyrene" sensitive="true" />
+ <box x="muon_sens8_x" y="muon_sens8_y" z="muon_sens_z" py="-muon_sens8_py" pz="muon_sens8_pz" material="Polystyrene" sensitive="true" />
+ </layer>
+ </detector>
+ </detectors>
+
+ <readouts>
+ <readout name="MUON_HITS">
+ <segmentation type="GridXYZ" gridSizeX="5.0" gridSizeY="5.0" gridSizeZ="0.0" />
+ <!--<id>system:6,side:-2,layer:4,slice:3,ix:32:-8,iy:-6</id>-->
+ <id>system:6,side:-2,layer:4,slice:3,x:32:-8,y:-6</id>
+ </readout>
+ </readouts>
+
+ <includes>
+ <gdmlFile file="./testResources/org/lcsim/geometry/subdetector/hps_2014_muon_vacuum_flange.gdml" />
+ </includes>
+
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTest.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTest.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTest.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,254 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPSTest">
+ <comment>HPS test setup</comment>
+ </info>
+
+ <define>
+
+<!-- <constant name="pi" value="3.14159" />-->
+ <constant name="SA" value="0.10" />
+ <constant name="SA2" value="0.05" />
+
+ <!-- world -->
+ <constant name="world_side" value="10000.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="200.0*cm"/>
+ <constant name="tracking_region_min" value="5.0*cm"/>
+ <constant name="tracking_region_zmax" value="100.0*cm"/>
+
+ <constant name="xCent1" value="10*cm"/>
+ <constant name="xCent2" value="20*cm"/>
+ <constant name="xCent3" value="30*cm"/>
+ <constant name="xCent4" value="50*cm"/>
+ <constant name="xCent5" value="70*cm"/>
+
+ <constant name="zgap1" value="0.30*cm" />
+ <constant name="zgap2" value="0.60*cm" />
+ <constant name="zgap3" value="0.90*cm" />
+ <constant name="zgap4" value="1.5*cm" />
+ <constant name="zgap5" value="2.1*cm" />
+
+ <constant name="zPlaneDist" value="1.0*cm"/>
+
+ <constant name="modLength" value="10.0*cm"/>
+ <constant name="modWidth" value="4.0*cm"/>
+
+ <constant name="ecal_front" value="13.3/2*mm" />
+ <constant name="ecal_back" value="16/2*mm" />
+ <!--<constant name="ecal_back" value="30/2*mm"/>-->
+ <constant name="ecal_z" value="160/2*mm" />
+
+
+ <!-- tracking region -->
+<!--
+ <constant name="tracking_region_radius" value="200.0*cm"/>
+ <constant name="tracking_region_min" value="5.0*cm"/>
+ <constant name="tracking_region_zmax" value="100.0*cm"/>
+
+ <constant name="xCent1" value="10*cm" />
+ <constant name="xCent2" value="20*cm" />
+
+ <constant name="xCent3" value="30*cm" />
+ <constant name="xCent4" value="50*cm" />
+ <constant name="xCent5" value="70*cm" />
+ <constant name="xCent6" value="90*cm" />
+
+ <constant name="zgap1" value="0.30*cm" />
+ <constant name="zgap2" value="0.60*cm" />
+
+ <constant name="zgap3" value="0.498*cm" />
+ <constant name="zgap4" value="0.830*cm" />
+ <constant name="zgap5" value="1.162*cm" />
+ <constant name="zgap6" value="1.494*cm" />
+
+ <constant name="zPlaneDist" value="1.0*cm" />
+
+ <constant name="modLength" value="10.0*cm" />
+ <constant name="modWidth" value="4.0*cm" />
+-->
+
+ </define>
+
+ <materials>
+ <material name="LeadTungstate">
+ <D value="8.28" unit="g/cm3"/>
+ <composite n="1" ref="Pb"/>
+ <composite n="1" ref="W"/>
+ <composite n="4" ref="O"/>
+ </material>
+ </materials>
+
+ <detectors>
+
+ <detector id="13"
+ name="HPSEcalTest"
+ type="HPSEcal"
+ insideTrackingVolume="true"
+ readout="EcalHits"
+ >
+ <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="120.0*cm" />
+ </detector>
+
+ <detector id="1" name="Tracker" type="SiTrackerFixedTarget2" readout="TrackerHits" combineHits="true" reflect="true" flipSA="true">
+ <module name="Module1">
+ <trd x1="modWidth/2" x2="modWidth/2" z="modLength/2" />
+ <module_component thickness="0.032*cm" material = "Silicon" sensitive="true"/><!-- X0=0.32% -->
+ <module_component thickness="0.02*cm" material = "Carbon" sensitive="false"/> <!-- X0=0.1% -->
+ </module>
+
+ <layer id="1">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap1+modWidth)/2" nz="1" zStep="modWidth" phi0="0.0" x="xCent1" dx="0.0*cm" module="Module1"/>
+ </layer>
+ <layer id="2">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap1+modWidth)/2" nz="1" zStep="modWidth" phi0="SA" x="xCent1+zPlaneDist" dx="0.0*cm" module="Module1"/>
+ </layer>
+
+ <layer id="3">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap2+modWidth)/2" nz="1" zStep="modWidth" phi0="0.0" x="xCent2" dx="0.0*cm" module="Module1"/>
+ </layer>
+ <layer id="4">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap2+modWidth)/2" nz="1" zStep="modWidth" phi0="SA" x="xCent2+zPlaneDist" dx="0.0*cm" module="Module1"/>
+ </layer>
+
+
+ <layer id="5">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap3+modWidth)/2" nz="1" zStep="modWidth" phi0="0.0" x="xCent3" dx="0.0*cm" module="Module1"/>
+ </layer>
+ <layer id="6">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap3+modWidth)/2" nz="1" zStep="modWidth" phi0="SA" x="xCent3+zPlaneDist" dx="0.0*cm" module="Module1"/>
+ </layer>
+
+ <layer id="7">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap4+modWidth)/2" nz="1" zStep="modWidth" phi0="0.0" x="xCent4" dx="0.0*cm" module="Module1"/>
+ </layer>
+ <layer id="8">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap4+modWidth)/2" nz="1" zStep="modWidth" phi0="SA2" x="xCent4+zPlaneDist" dx="0.0*cm" module="Module1"/>
+ </layer>
+
+ <layer id="9">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap5+modWidth)/2" nz="1" zStep="modWidth" phi0="0.0" x="xCent5" dx="0.0*cm" module="Module1"/>
+ </layer>
+ <layer id="10">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap5+modWidth)/2" nz="1" zStep="modWidth" phi0="SA2" x="xCent5+zPlaneDist" dx="0.0*cm" module="Module1"/>
+ </layer>
+
+
+ </detector>
+
+<!--
+Proposal detector
+ <detector id="1" name="Tracker" type="SiTrackerFixedTarget2"
+ readout="TrackerHits" combineHits="true" reflect="true">
+ <module name="Module1">
+ <trd x1="modWidth/2" x2="modWidth/2" z="modLength/2" />
+ <module_component thickness="0.032*cm" material="Silicon"
+ sensitive="true" />
+ <module_component thickness="0.02*cm" material="Carbon"
+ sensitive="false" />
+ </module>
+
+ <layer id="1">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap1+modWidth)/2"
+ nz="1" zStep="modWidth" phi0="0.0" x="xCent1" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="2">
+ <quadrant yStart="-1*modWidth/2" ny="2" yStep="modWidth"
+ zStart="(zgap1+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent1+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+
+ <layer id="3">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap2+modWidth)/2"
+ nz="2" zStep="modWidth" phi0="0.0" x="xCent2" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="4">
+ <quadrant yStart="-1*modWidth" ny="3" yStep="modWidth"
+ zStart="(zgap2+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent2+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+ <layer id="5">
+ <quadrant yStart="0" ny="1" yStep="modLength" zStart="(zgap3+modWidth)/2"
+ nz="2" zStep="modWidth" phi0="0.0" x="xCent3" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="6">
+ <quadrant yStart="-1*modWidth" ny="3" yStep="modWidth"
+ zStart="(zgap3+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent3+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+
+
+ <layer id="7">
+ <quadrant yStart="-2*modWidth" ny="5" yStep="modWidth"
+ zStart="(zgap4+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0-SA"
+ x="xCent4" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="8">
+ <quadrant yStart="-2*modWidth" ny="5" yStep="modWidth"
+ zStart="(zgap4+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent4+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+ <layer id="9">
+ <quadrant yStart="-3*modWidth" ny="7" yStep="modWidth"
+ zStart="(zgap5+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0+SA"
+ x="xCent5" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="10">
+ <quadrant yStart="-3*modWidth" ny="7" yStep="modWidth"
+ zStart="(zgap5+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent5+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+ <layer id="11">
+ <quadrant yStart="-7*modWidth/2" ny="8" yStep="modWidth"
+ zStart="(zgap6+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0-SA"
+ x="xCent6" dx="0.0*cm" module="Module1" />
+ </layer>
+ <layer id="12">
+ <quadrant yStart="-7*modWidth/2" ny="8" yStep="modWidth"
+ zStart="(zgap6+modLength)/2" nz="1" zStep="modLength" phi0="pi/2.0"
+ x="xCent6+zPlaneDist" dx="0.0*cm" module="Module1" />
+ </layer>
+
+ </detector>
+-->
+
+ </detectors>
+
+ <readouts>
+ <readout name="EcalHits">
+ <segmentation type="GridXYZ" gridSizeX="0.0" gridSizeY="0.0" gridSizeZ="0.0" />
+ <id>system:6,side:-2,layer:4,ix:9,iy:9</id>
+ </readout>
+ <readout name="TargetHits">
+ <id>system:6,barrel:3,layer:4,wedge:4,module:12,sensor:1,side:32:-2,strip:12</id>
+ </readout>
+ <readout name="TrackerHits">
+ <id>system:6,barrel:3,layer:4,wedge:4,module:12,sensor:1,side:32:-2,strip:12</id>
+ </readout>
+ </readouts>
+ <fields>
+ <field type="Solenoid"
+ name="GlobalSolenoid"
+ inner_field="0.0"
+ outer_field="1.0"
+ zmax="17.78*cm"
+ inner_radius="10.0*cm"
+ outer_radius="101.44*cm"
+ />
+ </fields>
+
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2Test.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2Test.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2Test.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,145 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPS-Test-JLAB-v4pt0">
+ <comment>HPS Test Proposal detector</comment>
+ </info>
+
+ <define>
+
+ <!-- world -->
+ <constant name="world_side" value="500.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="200.0*cm"/>
+ <constant name="tracking_region_min" value="5.0*cm"/>
+ <constant name="tracking_region_zmax" value="100.0*cm"/>
+
+ <!-- SVT module dimensions -->
+ <constant name="moduleLength" value="100.0"/>
+ <constant name="moduleWidth" value="40.34"/>
+
+ <!-- SVT sensor dimensions -->
+ <constant name="sensorLength" value="98.33"/>
+ <!-- Sensor width is slightly under the real value of 38.34 mm so that sisim doesn't break. -->
+ <constant name="sensorWidth" value="38.3399"/>
+
+ <!-- module tilt for stereo angle -->
+ <constant name="SA" value="0.10" />
+ <constant name="SA2" value="0.05" />
+
+ <constant name="pi" value="3.14159" />
+ <!-- module z placement -->
+ <constant name="zCent1" value="10*cm"/>
+ <constant name="zCent2" value="20*cm"/>
+ <constant name="zCent3" value="30*cm"/>
+ <constant name="zCent4" value="50*cm"/>
+ <constant name="zCent5" value="70*cm"/>
+
+ <!-- module z gaps -->
+ <constant name="ygap1" value="0.30*cm" />
+ <constant name="ygap2" value="0.60*cm" />
+ <constant name="ygap3" value="0.90*cm" />
+ <constant name="ygap4" value="1.5*cm" />
+ <constant name="ygap5" value="2.1*cm" />
+
+ <!-- module z plane distance -->
+ <constant name="zPlaneDist" value="1.0*cm"/>
+
+ <!-- ecal -->
+ <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" />
+
+ </define>
+
+ <materials>
+
+ <!-- Set tracking material to vacuum. -->
+ <material name="TrackingMaterial">
+ <D type="density" unit="g/cm3" value="0.0000000000000001"/>
+ <fraction n="1.0" ref="Air" />
+ </material>
+
+ </materials>
+
+ <detectors>
+
+ <detector id="1" name="Tracker" type="HPSTracker2" readout="TrackerHits" combineHits="true">
+ <comment> The Silicon Vertex Tracker.</comment>
+ <module name="TestRunModule">
+ <box x="moduleLength" y="moduleWidth" />
+ <module_component thickness="0.032*cm" material = "Silicon" sensitive="true">
+ <dimensions x="sensorLength" y="sensorWidth" />
+ </module_component>
+ <module_component thickness="0.02*cm" material = "Carbon" sensitive="false"/>
+ </module>
+ <layer id="1">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="21.67" z="100.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-21.67" z="100.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="2">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="21.67" z="110.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-21.67" z="110.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="3">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="23.17" z="200.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-23.17" z="200.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="4">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="23.17" z="210.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-23.17" z="210.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="5">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="24.67" z="300.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-24.67" z="300.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="6">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="24.67" z="310.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-24.67" z="310.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="7">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="27.67" z="500.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-27.67" z="500.0" rx="0.0" ry="0.0" rz="-1.6207963267948966"/>
+ </layer>
+ <layer id="8">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="27.67" z="510.0" rx="0.0" ry="3.14159" rz="-4.762386326794896"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-27.67" z="510.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="9">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="30.67" z="700.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-30.67" z="700.0" rx="0.0" ry="0.0" rz="-1.6207963267948966"/>
+ </layer>
+ <layer id="10">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="30.67" z="710.0" rx="0.0" ry="3.14159" rz="-4.762386326794896"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-30.67" z="710.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ </detector>
+ </detectors>
+
+ <readouts>
+ <readout name="TrackerHits">
+ <id>system:6,barrel:3,layer:4,module:12,sensor:1,side:32:-2,strip:12</id>
+ </readout>
+ </readouts>
+
+ <fields>
+ <field type="BoxDipole"
+ name="AnalyzingDipole"
+ x="0*cm"
+ y="0*cm"
+ z="45.22*cm"
+ dx="22.86*cm"
+ dy="7.62*cm"
+ dz="46.22*cm"
+ bx="0.0"
+ by="-0.5"
+ bz="0.0">
+ </field>
+ </fields>
+
+</lccdd>
Added: java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HpsTestRunSiSensorConverterTest.xml
=============================================================================
--- java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HpsTestRunSiSensorConverterTest.xml (added)
+++ java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HpsTestRunSiSensorConverterTest.xml Tue Oct 6 11:36:11 2015
@@ -0,0 +1,145 @@
+<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
+
+ <info name="HPS-Test-JLAB-v4pt0">
+ <comment>HPS Test Proposal detector</comment>
+ </info>
+
+ <define>
+
+ <!-- world -->
+ <constant name="world_side" value="500.0*cm" />
+ <constant name="world_x" value="world_side" />
+ <constant name="world_y" value="world_side" />
+ <constant name="world_z" value="world_side" />
+
+ <!-- tracking region -->
+ <constant name="tracking_region_radius" value="200.0*cm"/>
+ <constant name="tracking_region_min" value="5.0*cm"/>
+ <constant name="tracking_region_zmax" value="100.0*cm"/>
+
+ <!-- SVT module dimensions -->
+ <constant name="moduleLength" value="100.0"/>
+ <constant name="moduleWidth" value="40.34"/>
+
+ <!-- SVT sensor dimensions -->
+ <constant name="sensorLength" value="98.33"/>
+ <!-- Sensor width is slightly under the real value of 38.34 mm so that sisim doesn't break. -->
+ <constant name="sensorWidth" value="38.3399"/>
+
+ <!-- module tilt for stereo angle -->
+ <constant name="SA" value="0.10" />
+ <constant name="SA2" value="0.05" />
+
+ <constant name="pi" value="3.14159" />
+ <!-- module z placement -->
+ <constant name="zCent1" value="10*cm"/>
+ <constant name="zCent2" value="20*cm"/>
+ <constant name="zCent3" value="30*cm"/>
+ <constant name="zCent4" value="50*cm"/>
+ <constant name="zCent5" value="70*cm"/>
+
+ <!-- module z gaps -->
+ <constant name="ygap1" value="0.30*cm" />
+ <constant name="ygap2" value="0.60*cm" />
+ <constant name="ygap3" value="0.90*cm" />
+ <constant name="ygap4" value="1.5*cm" />
+ <constant name="ygap5" value="2.1*cm" />
+
+ <!-- module z plane distance -->
+ <constant name="zPlaneDist" value="1.0*cm"/>
+
+ <!-- ecal -->
+ <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" />
+
+ </define>
+
+ <materials>
+
+ <!-- Set tracking material to vacuum. -->
+ <material name="TrackingMaterial">
+ <D type="density" unit="g/cm3" value="0.0000000000000001"/>
+ <fraction n="1.0" ref="Air" />
+ </material>
+
+ </materials>
+
+ <detectors>
+
+ <detector id="1" name="Tracker" type="HPSTracker2" readout="TrackerHits" combineHits="true">
+ <comment> The Silicon Vertex Tracker.</comment>
+ <module name="TestRunModule" type="HpsTestRunSiSensor">
+ <box x="moduleLength" y="moduleWidth" />
+ <module_component thickness="0.032*cm" material = "Silicon" sensitive="true">
+ <dimensions x="sensorLength" y="sensorWidth" />
+ </module_component>
+ <module_component thickness="0.02*cm" material = "Carbon" sensitive="false"/>
+ </module>
+ <layer id="1">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="21.67" z="100.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-21.67" z="100.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="2">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="21.67" z="110.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-21.67" z="110.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="3">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="23.17" z="200.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-23.17" z="200.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="4">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="23.17" z="210.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-23.17" z="210.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="5">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="24.67" z="300.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-24.67" z="300.0" rx="0.0" ry="0.0" rz="-1.6707963267948966"/>
+ </layer>
+ <layer id="6">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="24.67" z="310.0" rx="0.0" ry="3.14159" rz="-4.812386326794897"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-24.67" z="310.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="7">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="27.67" z="500.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-27.67" z="500.0" rx="0.0" ry="0.0" rz="-1.6207963267948966"/>
+ </layer>
+ <layer id="8">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="27.67" z="510.0" rx="0.0" ry="3.14159" rz="-4.762386326794896"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-27.67" z="510.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ <layer id="9">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="30.67" z="700.0" rx="0.0" ry="0.0" rz="-1.5707963267948966"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-30.67" z="700.0" rx="0.0" ry="0.0" rz="-1.6207963267948966"/>
+ </layer>
+ <layer id="10">
+ <module_placement name="TestRunModule" id="0" x="0.0" y="30.67" z="710.0" rx="0.0" ry="3.14159" rz="-4.762386326794896"/>
+ <module_placement name="TestRunModule" id="1" x="0.0" y="-30.67" z="710.0" rx="0.0" ry="3.14159" rz="-4.712386326794896"/>
+ </layer>
+ </detector>
+ </detectors>
+
+ <readouts>
+ <readout name="TrackerHits">
+ <id>system:6,barrel:3,layer:4,module:12,sensor:1,side:32:-2,strip:12</id>
+ </readout>
+ </readouts>
+
+ <fields>
+ <field type="BoxDipole"
+ name="AnalyzingDipole"
+ x="0*cm"
+ y="0*cm"
+ z="45.22*cm"
+ dx="22.86*cm"
+ dy="7.62*cm"
+ dz="46.22*cm"
+ bx="0.0"
+ by="-0.5"
+ bz="0.0">
+ </field>
+ </fields>
+
+</lccdd>
Modified: java/trunk/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java
=============================================================================
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java (original)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java Tue Oct 6 11:36:11 2015
@@ -1,30 +1,63 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
package org.hps.recon.tracking;
import java.util.ArrayList;
import java.util.List;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.PhysicalVolumeNavigator;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.geometry.subdetector.HPSTracker;
+import org.lcsim.geometry.subdetector.HPSTracker2;
import org.lcsim.recon.tracking.seedtracker.MaterialXPlane;
/**
- *
* Extension to lcsim MaterialManager to allow more flexibility in track reconstruction
- *
+ *
* @author Per Hansson <[log in to unmask]>
*/
public class MaterialManager extends org.lcsim.recon.tracking.seedtracker.MaterialManager {
+ /**
+ * Get the path groups for SiTrackerEndcap2, which has modules placed directly in the tracking volume.
+ */
+ static private class HPSTracker2VolumeGrouper implements SubdetectorVolumeGrouper {
+
+ @Override
+ public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
+ // System.out.println(this.getClass().getSimpleName() + ".getPathGroups()");
+ final List<List<String>> pathGroups = new ArrayList<List<String>>();
+ // Layer loop.
+ for (final IDetectorElement layer : subdet.getDetectorElement().getChildren()) {
+ final List<String> modulePaths = new ArrayList<String>();
+
+ // Module loop.
+ for (final IDetectorElement module : layer.getChildren()) {
+ final String path = "";
+ PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(), path);
+ }
+
+ // Add module paths to this layer.
+ pathGroups.add(modulePaths);
+ }
+ return pathGroups;
+ }
+ }
+
+ private final static List<MaterialXPlane> _emptyMaterialXPlaneList = new ArrayList<MaterialXPlane>();
+
protected boolean _includeMS = true;
- private final static List<MaterialXPlane> _emptyMaterialXPlaneList = new ArrayList<MaterialXPlane>();
public MaterialManager() {
super();
+
+ // Add volume groupers for HPS tracker types.
+ final SubdetectorVolumeGrouper endcap2Grouper = new SiTrackerEndap2VolumeGrouper();
+ subdetGroups.put(HPSTracker.class, endcap2Grouper);
+ subdetGroups.put(HPSTracker2.class, new HPSTracker2VolumeGrouper());
}
- public MaterialManager(boolean includeMS) {
+ public MaterialManager(final boolean includeMS) {
super();
this._includeMS = includeMS;
}
@@ -35,7 +68,7 @@
}
@Override
- public void setDebug(boolean debug) {
+ public void setDebug(final boolean debug) {
super.setDebug(debug);
}
|