Author: [log in to unmask] Date: Tue Oct 6 11:38:04 2015 New Revision: 3668 Log: Changes to MaterialManager from classes being moved to HPS. Modified: projects/lcsim/trunk/tracking/src/main/java/org/lcsim/recon/tracking/seedtracker/MaterialManager.java Modified: projects/lcsim/trunk/tracking/src/main/java/org/lcsim/recon/tracking/seedtracker/MaterialManager.java ============================================================================= --- projects/lcsim/trunk/tracking/src/main/java/org/lcsim/recon/tracking/seedtracker/MaterialManager.java (original) +++ projects/lcsim/trunk/tracking/src/main/java/org/lcsim/recon/tracking/seedtracker/MaterialManager.java Tue Oct 6 11:38:04 2015 @@ -26,8 +26,6 @@ import org.lcsim.geometry.Detector; import org.lcsim.geometry.Subdetector; import org.lcsim.geometry.subdetector.DiskTracker; -import org.lcsim.geometry.subdetector.HPSTracker; -import org.lcsim.geometry.subdetector.HPSTracker2; import org.lcsim.geometry.subdetector.MultiLayerTracker; import org.lcsim.geometry.subdetector.PolyconeSupport; import org.lcsim.geometry.subdetector.SiTrackerBarrel; @@ -37,57 +35,28 @@ import org.lcsim.geometry.subdetector.SiTrackerSpectrometer; /** - * Rewrite and refactor of Rich's {@link MaterialManager} class to handle Subdetector types. - * This class should now group together SiTrackerEndcap2 layers correctly. - * + * Rewrite and refactor of Rich's {@link MaterialManager} class to handle Subdetector types. This class should now group + * together SiTrackerEndcap2 layers correctly. + * * @author Rich Partridge * @author Jeremy McCormick * @author Matt Graham - * * @version $Id: MaterialManager.java,v 1.21 2013/07/12 20:47:35 phansson Exp $ */ -public class MaterialManager -{ - // Variables from original MaterialManager class. - protected boolean DEBUG = false; // enable debug output to System.out - private static final boolean TUBE_ONLY = false; // only use Tube elements - // for calculating volume. - private List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>(); - private List<MaterialCylinder> _matcyl = new ArrayList<MaterialCylinder>(); - private List<MaterialDisk> _matdsk = new ArrayList<MaterialDisk>(); - private List<MaterialXPlane> _matxpl = new ArrayList<MaterialXPlane>(); - private HashMap<ISolid, Double> solid_vol_map = new HashMap<ISolid, Double>(400); - private static double _rmax; - private static double _zmax = 1800.; - private static ITransform3D _detToTrk; - - private boolean _useDefaultXPlanes = true; - /** - * VolumeGroup handlers for Subdetector types. - */ - private Map<Class, SubdetectorVolumeGrouper> subdetGroups = new HashMap<Class, SubdetectorVolumeGrouper>(); - - /** - * Interface for getting the path groupings for different Subdetector types. - */ - private interface SubdetectorVolumeGrouper - { - List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol); - } +public class MaterialManager { /** * Get the path groupings for barrel Subdetectors with physical layers one level below top. This will handle * SiTrackerBarrel and MultiLayerTracker Subdetector types. */ - static private class BarrelLayerVolumeGroup implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - List<List<String>> pathGroups = new ArrayList<List<String>>(); - for (IDetectorElement layer : subdet.getDetectorElement().getChildren()) - { - List<String> layerPaths = new ArrayList<String>(); - String path = ""; + public static final class BarrelLayerVolumeGroup implements SubdetectorVolumeGrouper { + + @Override + public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) { + final List<List<String>> pathGroups = new ArrayList<List<String>>(); + for (final IDetectorElement layer : subdet.getDetectorElement().getChildren()) { + final List<String> layerPaths = new ArrayList<String>(); + final String path = ""; PhysicalVolumeNavigator.getLeafPaths(layerPaths, layer.getGeometry().getPhysicalVolume(), path); pathGroups.add(layerPaths); } @@ -96,78 +65,71 @@ } /** + * Default VolumeGroup for endcaps with physical layers. + */ + public static final class EndcapVolumeGrouper implements SubdetectorVolumeGrouper { + + @Override + public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) { + final List<List<String>> pathGroups = new ArrayList<List<String>>(); + // Positive and negative endcap loop. + for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) { + // Layer loop. + for (final IDetectorElement layer : endcaps.getChildren()) { + final List<String> layerPaths = new ArrayList<String>(); + final String path = ""; + PhysicalVolumeNavigator.getLeafPaths(layerPaths, layer.getGeometry().getPhysicalVolume(), path); + pathGroups.add(layerPaths); + } + } + return pathGroups; + } + + } + + /** * Get the path groups for a PolyconeSupport, which is a single path. */ - static private class PolyconeSupportVolumeGrouper implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - List<List<String>> pathGroups = new ArrayList<List<String>>(); - String path = ""; - List<String> supportPath = new ArrayList<String>(); - IPhysicalVolume supportPV = - subdet.getDetectorElement().getChildren().get(0).getGeometry().getPhysicalVolume(); + public static final class PolyconeSupportVolumeGrouper implements SubdetectorVolumeGrouper { + + @Override + public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) { + final List<List<String>> pathGroups = new ArrayList<List<String>>(); + final String path = ""; + final List<String> supportPath = new ArrayList<String>(); + final IPhysicalVolume supportPV = subdet.getDetectorElement().getChildren().get(0).getGeometry() + .getPhysicalVolume(); PhysicalVolumeNavigator.getLeafPaths(supportPath, supportPV, path); pathGroups.add(supportPath); return pathGroups; } } - + /** * Get the path groups for SiTrackerEndcap2, which has modules placed directly in the tracking volume. */ - static private class HPSTracker2VolumeGrouper implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - System.out.println(this.getClass().getSimpleName() + ".getPathGroups()"); - List<List<String>> pathGroups = new ArrayList<List<String>>(); - // Layer loop. - for (IDetectorElement layer : subdet.getDetectorElement().getChildren()) - { - List<String> modulePaths = new ArrayList<String>(); - - // Module loop. - for (IDetectorElement module : layer.getChildren()) - { - String path = ""; - PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(), path); - } - - // Add module paths to this layer. - pathGroups.add(modulePaths); - } - return pathGroups; - } - } - - /** - * Get the path groups for SiTrackerEndcap2, which has modules placed directly in the tracking volume. - */ - static private class SiTrackerEndap2VolumeGrouper implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - List<List<String>> pathGroups = new ArrayList<List<String>>(); + public static final class SiTrackerEndap2VolumeGrouper implements SubdetectorVolumeGrouper { + + @Override + public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) { + final List<List<String>> pathGroups = new ArrayList<List<String>>(); // Positive and negative endcap loop. - for (IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) - { + for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) { // Layer loop. - for (IDetectorElement layer : endcaps.getChildren()) - { - List<String> modulePaths = new ArrayList<String>(); + for (final IDetectorElement layer : endcaps.getChildren()) { + final List<String> modulePaths = new ArrayList<String>(); // Module loop. - for (IDetectorElement module : layer.getChildren()) - { - String path = ""; - PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(), path); + for (final IDetectorElement module : layer.getChildren()) { + final String path = ""; + PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(), + path); } - - //for (String p : modulePaths) { - // System.out.println("adding path: " + p); - //} - + + // for (String p : modulePaths) { + // System.out.println("adding path: " + p); + // } + // Add module paths to this layer. pathGroups.add(modulePaths); } @@ -179,24 +141,21 @@ /** * Get the path groups for SiTrackerFixedTarget2 */ - static private class SiTrackerFixedTarget2VolumeGrouper implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - List<List<String>> pathGroups = new ArrayList<List<String>>(); + public static final class SiTrackerFixedTarget2VolumeGrouper implements SubdetectorVolumeGrouper { + + @Override + public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) { + final List<List<String>> pathGroups = new ArrayList<List<String>>(); // Positive and negative endcap loop. - for (IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) - { + for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) { // Layer loop. - for (IDetectorElement layer : endcaps.getChildren()) - { - List<String> modulePaths = new ArrayList<String>(); + for (final IDetectorElement layer : endcaps.getChildren()) { + final List<String> modulePaths = new ArrayList<String>(); // System.out.println(layer.getName()); // Module loop. - for (IDetectorElement module : layer.getChildren()) - { - String path = ""; + for (final IDetectorElement module : layer.getChildren()) { + final String path = ""; PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(), path); } @@ -208,54 +167,215 @@ } } - - /** - * Default VolumeGroup for endcaps with physical layers. - */ - static private class EndcapVolumeGrouper implements SubdetectorVolumeGrouper - { - public List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol) - { - List<List<String>> pathGroups = new ArrayList<List<String>>(); - // Positive and negative endcap loop. - for (IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) - { - // Layer loop. - for (IDetectorElement layer : endcaps.getChildren()) - { - List<String> layerPaths = new ArrayList<String>(); - String path = ""; - PhysicalVolumeNavigator.getLeafPaths(layerPaths, layer.getGeometry().getPhysicalVolume(), path); - pathGroups.add(layerPaths); - } - } - return pathGroups; - } - - } + /** + * Interface for getting the path groupings for different Subdetector types. + */ + public interface SubdetectorVolumeGrouper { + + List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol); + } + + /** + * A UniquePV is a wrapper around IPhysicalVolumePath which provides some convenience methods and caches + * transformations. + */ + static class UniquePV { + + IPhysicalVolumeNavigator nav; + IPhysicalVolumePath path; + ITransform3D transform = null; + + /** + * Generates a top-level UniquePV. + * + * @param root The top-level IPhysicalVolume + * @param navigator The IPhysicalVolumeNavigator associated with the detector + */ + public UniquePV(final IPhysicalVolume root, final IPhysicalVolumeNavigator navigator) { + path = new PhysicalVolumePath(); + nav = navigator; + path.add(root); + } + + /** + * Generates a UniquePV from a path. (Shallow copy of path) + * + * @param path + * @param navigator + */ + public UniquePV(final IPhysicalVolumePath path, final IPhysicalVolumeNavigator navigator) { + this.path = path; + nav = navigator; + } + + /** + * Creates a UniquePV that is a daughter of the current UniquePV (deep copy made) + * + * @param daughter + * @return + */ + public UniquePV createDaughterUniquePV(final IPhysicalVolume daughter) { + final IPhysicalVolumePath np = new PhysicalVolumePath(); + np.addAll(path); + np.add(daughter); + return new UniquePV(np, nav); + } + + /** + * Returns the local-to-global transform + * + * @return an ITransform3D from local coordinates to global coordinates. + */ + public ITransform3D getLtoGTransform() { + if (transform == null) { + transform = nav.getTransform(path); + } + return transform; + } + + /** + * Returns the IPhysicalVolume (the last element of the path) + */ + public IPhysicalVolume getPV() { + return path.getLeafVolume(); + } + + /** + * Returns the solid associated with the physical volume. + * + * @return + */ + public ISolid getSolid() { + return this.getPV().getLogicalVolume().getSolid(); + } + + /** + * Transforms the given vector from local to global coords. + * + * @param v the untransformed local Hep3Vector + * @return the transformed global Hep3Vector + */ + public Hep3Vector localToGlobal(final Hep3Vector v) { + + return this.getLtoGTransform().transformed(v); + } + + @Override + public String toString() { + return path.toString(); + } + } + + /** + * A "struct" holding geometry information about lists of physical volumes + */ + class VolumeGroupInfo { + + double rmax = 0.0; + double rmin = 1.e10; + double vtot = 0.0; + double vtot_tube_only = 0.; + double weighted_r = 0.0; + double weighted_y = 0.0; + double weighted_z = 0.0; + double X0 = 0.0; + double xmax = -1.e10; + double xmin = 1.e10; + double ymax = -1.e10; + // mg 3/14/11 MaterialXPlane info + double ymin = 1.e10; + double zmax = -1.e10; + double zmin = 1.e10; + + } + + /** + * A "struct" holding geometry information about a single physical volume + */ + class VolumeInfo { + + double rmax = 0.0; + double rmin = 1.e10; + double xmax = -1.e10; + double xmin = 1.e10; + double ymax = -1.e10; + // mg 3/14/11 MaterialXPlane info + double ymin = 1.e10; + double zmax = -1.e10; + double zmin = 1.e10; + } + + private static ITransform3D _detToTrk; + private static double _rmax; + + private static double _zmax = 1800.; + + private static final boolean TUBE_ONLY = false; // only use Tube elements + + public static double getRMax() { + return _rmax; + } + + public static double getZMax() { + return _zmax; + } + + private static List<UniquePV> makeUniquePVList(final IPhysicalVolumeNavigator nav, + final IPhysicalVolume trackingVol, final List<String> paths) { + final List<UniquePV> uniqPVs = new ArrayList<UniquePV>(); + for (final String path : paths) { + /** + * Create the path object, prepending tracking volume name, as the paths are relative to Subdetector. + */ + final IPhysicalVolumePath pvPath = nav.getPath("/" + trackingVol.getName() + path); + + /** + * Create the UniquePV for MaterialManager. + */ + uniqPVs.add(new UniquePV(pvPath, nav)); + } + return uniqPVs; + } + + private final List<MaterialCylinder> _matcyl = new ArrayList<MaterialCylinder>(); + + private final List<MaterialDisk> _matdsk = new ArrayList<MaterialDisk>(); + + // for calculating volume. + private final List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>(); + + private final List<MaterialXPlane> _matxpl = new ArrayList<MaterialXPlane>(); + + private boolean _useDefaultXPlanes = true; + + // Variables from original MaterialManager class. + protected boolean DEBUG = false; // enable debug output to System.out + + private final HashMap<ISolid, Double> solid_vol_map = new HashMap<ISolid, Double>(400); + + /** + * VolumeGroup handlers for Subdetector types. + */ + protected final Map<Class, SubdetectorVolumeGrouper> subdetGroups = new HashMap<Class, SubdetectorVolumeGrouper>(); /** * Creates a new instance of MaterialManager */ - public MaterialManager() - { + public MaterialManager() { // Barrels. - SubdetectorVolumeGrouper barrelGrouper = new BarrelLayerVolumeGroup(); + final SubdetectorVolumeGrouper barrelGrouper = new BarrelLayerVolumeGroup(); subdetGroups.put(SiTrackerBarrel.class, barrelGrouper); subdetGroups.put(MultiLayerTracker.class, barrelGrouper); // Endcaps. - SubdetectorVolumeGrouper endcapGrouper = new EndcapVolumeGrouper(); + final SubdetectorVolumeGrouper endcapGrouper = new EndcapVolumeGrouper(); subdetGroups.put(SiTrackerEndcap.class, endcapGrouper); subdetGroups.put(DiskTracker.class, endcapGrouper); // SiTrackerEndcap2. - SubdetectorVolumeGrouper endcap2Grouper = new SiTrackerEndap2VolumeGrouper(); + final SubdetectorVolumeGrouper endcap2Grouper = new SiTrackerEndap2VolumeGrouper(); subdetGroups.put(SiTrackerEndcap2.class, endcap2Grouper); subdetGroups.put(SiTrackerSpectrometer.class, endcap2Grouper); - subdetGroups.put(HPSTracker.class, endcap2Grouper); - - subdetGroups.put(HPSTracker2.class, new HPSTracker2VolumeGrouper()); // SiTrackerFixedTarget2. subdetGroups.put(SiTrackerFixedTarget2.class, new SiTrackerFixedTarget2VolumeGrouper()); @@ -265,37 +385,73 @@ } /** - * Turn on/off debugging output. - * @param debug True if debugging should be enabled; false if not. - */ - public void setDebug(boolean debug) - { - this.DEBUG = debug; - } - - public void setDefaultXPlaneUsage(boolean useDefault) - { - _useDefaultXPlanes = useDefault; - } - - /** - * Setup tracking volume parameters. - * - * @param det The Detector. - */ - private void setupTrackingVolume(Detector det) - { - // Find the envelope of the tracking volume - ISolid trkvol = det.getTrackingVolume().getLogicalVolume().getSolid(); - if (trkvol instanceof Tube) - { - Tube trktube = (Tube)trkvol; - _rmax = trktube.getOuterRadius(); - _zmax = trktube.getZHalfLength(); - if (DEBUG) - { - System.out.println("Ecal radius = " + _rmax); - System.out.println("ECal inner Z = " + _zmax); + * Calculates the VolumeGroupInfo for a set of {@link UniquePV} objects. + * + * @param uniqPVs + * @param vgi + */ + private void addVolumeGroupInfo(final List<UniquePV> uniqPVs, final VolumeGroupInfo vgi) { + double vtot; + if (TUBE_ONLY) { + vtot = vgi.vtot_tube_only; + } else { + vtot = vgi.vtot; + } + + // Handle Polycone. + if (uniqPVs.get(0).getPV().getLogicalVolume().getSolid() instanceof Polycone) { + this.handlePolycone(uniqPVs.get(0).getPV()); + } + + if (vtot > 0.) { + + // Calculate the average radiation length for this volume + + // Determine if this volume should be modeled as barrel or disk + if (this.isXPlane(vgi.xmin, vgi.xmax)) { + // Calculate the weighted radius of the elements + final double zlen = vgi.zmax - vgi.zmin; + final double ylen = vgi.ymax - vgi.ymin; + final double thickness = vtot / (ylen * zlen * vgi.X0); + final double x = (vgi.xmax + vgi.xmin) / 2; + + if (DEBUG) { + System.out.println("Treating as a XPlane...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: " + + vgi.zmax + "| vtot: " + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin + + "| rmax: " + vgi.rmax + "| xmin: " + vgi.xmin + "| xmax: " + vgi.xmax); + System.out.println(); + } + if (!_useDefaultXPlanes) { + if (x > 0.1) { + _matxpl.add(new MaterialXPlane(vgi.ymin, vgi.ymax, vgi.zmin, vgi.zmax, x, thickness)); + } + } else { + _matxpl.add(new MaterialXPlane(vgi.ymin, vgi.ymax, vgi.zmin, vgi.zmax, x, thickness)); + } + } else if (this.isCylinder(vgi.rmin, vgi.rmax, vgi.zmin, vgi.zmax)) { + // Calculate the weighted radius of the elements + final double zlen = vgi.zmax - vgi.zmin; + final double thickness = vtot / (2. * Math.PI * vgi.weighted_r * zlen * vgi.X0); + + if (DEBUG) { + System.out.println("Treating as a Cylinder...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: " + + vgi.zmax + "| vtot: " + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin + + "| rmax: " + vgi.rmax); + System.out.println(); + } + + _matcyl.add(new MaterialCylinder(null, vgi.weighted_r, vgi.zmin, vgi.zmax, thickness)); + } else { + + final double thickness = vtot / (Math.PI * (vgi.rmax * vgi.rmax - vgi.rmin * vgi.rmin) * vgi.X0); + + if (DEBUG) { + System.out.println("x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: " + vgi.zmax + "| vtot: " + + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin + "| rmax: " + vgi.rmax); + System.out.println(); + } + + _matdsk.add(new MaterialDisk(null, vgi.rmin, vgi.rmax, vgi.weighted_z, thickness)); } } } @@ -303,67 +459,55 @@ /** * Build model using new VolumeGroup interface for each Subdetector type. */ - public void buildModel(Detector det) - { + public void buildModel(final Detector det) { // Get the default navigator. - IPhysicalVolumeNavigator nav = PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator(); + final IPhysicalVolumeNavigator nav = PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator(); // Get the tracking volume. - IPhysicalVolume trackingVol = det.getTrackingVolume(); + final IPhysicalVolume trackingVol = det.getTrackingVolume(); // Loop over subdetectors. - for (Subdetector subdet : det.getSubdetectorList()) - { + for (final Subdetector subdet : det.getSubdetectorList()) { // Only look at Subdetectors in the tracking region. - if (subdet.isInsideTrackingVolume()) - { - if (DEBUG) - { + if (subdet.isInsideTrackingVolume()) { + if (DEBUG) { System.out.println(); System.out.println(">>>> " + subdet.getName() + " >>>>"); } // Get the VolumeGrouper for this type. - SubdetectorVolumeGrouper subdetGrouper = subdetGroups.get(subdet.getClass()); + final SubdetectorVolumeGrouper subdetGrouper = subdetGroups.get(subdet.getClass()); // Can't handle this type. - if (subdetGrouper == null) - { + if (subdetGrouper == null) { System.out.println("WARNING: Can't handle Subdetector of type <" + subdet.getClass().getCanonicalName() + ">."); - } - else - { - if (DEBUG) - { + } else { + if (DEBUG) { System.out.println("Found VolumeGrouper <" + subdetGrouper.getClass().getName() + ">."); } // Make the list of path groups for this Subdetector. - List<List<String>> pathGroups = subdetGrouper.getPathGroups(subdet, trackingVol); - - if (DEBUG) - { + final List<List<String>> pathGroups = subdetGrouper.getPathGroups(subdet, trackingVol); + + if (DEBUG) { System.out.println("Got " + pathGroups.size() + " path groups."); } // Loop over path groups. - for (List<String> pathGroup : pathGroups) - { - if (DEBUG) - { + for (final List<String> pathGroup : pathGroups) { + if (DEBUG) { System.out.println("Adding next " + pathGroup.size() + " paths."); } // Make the UniquePV list expected by MaterialManager. - List<UniquePV> uniqPVs = makeUniquePVList(nav, trackingVol, pathGroup); + final List<UniquePV> uniqPVs = makeUniquePVList(nav, trackingVol, pathGroup); // Calculate VolumeGroupInfo for this path group. - VolumeGroupInfo vgi = performVolumeGroupCalculations(uniqPVs); + final VolumeGroupInfo vgi = this.performVolumeGroupCalculations(uniqPVs); // Debug print. - if (DEBUG) - { + if (DEBUG) { System.out.println("VolumeGroupInfo ..."); System.out.println(" rmax = " + vgi.rmax); System.out.println(" rmin = " + vgi.rmin); @@ -383,215 +527,81 @@ // Add the VolumeGroupInfo, which will setup the // material representation for this set of volumes. - addVolumeGroupInfo(uniqPVs, vgi); + this.addVolumeGroupInfo(uniqPVs, vgi); } } } } // Setup the tracking volume. - setupTrackingVolume(det); - } - - /** - * Calculates the VolumeGroupInfo for a set of {@link UniquePV} objects. - * @param uniqPVs - * @param vgi - */ - private void addVolumeGroupInfo(List<UniquePV> uniqPVs, VolumeGroupInfo vgi) - { - double vtot; - if (TUBE_ONLY) - { - vtot = vgi.vtot_tube_only; - } - else - { - vtot = vgi.vtot; - } - - // Handle Polycone. - if (uniqPVs.get(0).getPV().getLogicalVolume().getSolid() instanceof Polycone) - { - handlePolycone(uniqPVs.get(0).getPV()); - } - - if (vtot > 0.) - { - - // Calculate the average radiation length for this volume - - // Determine if this volume should be modeled as barrel or disk - if (isXPlane(vgi.xmin, vgi.xmax)) - { - // Calculate the weighted radius of the elements - double zlen = vgi.zmax - vgi.zmin; - double ylen = vgi.ymax - vgi.ymin; - double thickness = vtot / (ylen * zlen * vgi.X0); - double x=(vgi.xmax+vgi.xmin)/2; - + this.setupTrackingVolume(det); + } + + public List<MaterialCylinder> getMaterialCylinders() { + return _matcyl; + } + + public List<MaterialDisk> getMaterialDisks() { + return _matdsk; + } + + public List<MaterialPolyconeSegment> getMaterialPolyconeSegments() { + return _matpc; + } + + public List<MaterialXPlane> getMaterialXPlanes() { + return _matxpl; + } + + private double getVolumeOfSolid(final ISolid solid) { + if (solid_vol_map.containsKey(solid)) { + return solid_vol_map.get(solid).doubleValue(); + } else { + double vol; + try { + vol = solid.getCubicVolume(); + } catch (final Exception e) { + vol = 0.0; + } + + solid_vol_map.put(solid, vol); + return vol; + } + + } + + // special handling for Polycone... + private void handlePolycone(final IPhysicalVolume pv) { + final Polycone pc = (Polycone) pv.getLogicalVolume().getSolid(); + final IMaterial mat = pv.getLogicalVolume().getMaterial(); + + // Loop through each segment + for (int i = 0; i < pc.getNumberOfZPlanes() - 1; i++) { + final ZPlane zp1 = pc.getZPlane(i); + final ZPlane zp2 = pc.getZPlane(i + 1); + + final double z1 = zp1.getZ(); + final double z2 = zp2.getZ(); + final double vol = Polycone.getSegmentVolume(zp1, zp2); + final double zlen = Math.abs(z2 - z1); + final double ravg = 0.25 * (zp1.getRMax() + zp1.getRMin() + zp2.getRMax() + zp2.getRMin()); + final double ang = Math.atan2(0.5 * (zp1.getRMax() + zp1.getRMin() - zp2.getRMax() - zp2.getRMin()), zlen); + final double X0 = 10 * mat.getRadiationLength() / mat.getDensity(); + final double thickness = Math.cos(ang) * vol / (2 * Math.PI * ravg * zlen * X0); + + // This is a cylinder + if (zp1.getRMax() == zp2.getRMax() && zp1.getRMin() == zp2.getRMin()) { + _matcyl.add(new MaterialCylinder(pv, ravg, Math.min(z1, z2), Math.max(z1, z2), thickness)); if (DEBUG) { - System.out.println("Treating as a XPlane...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + - "| zmax: " + vgi.zmax + "| vtot: " + vtot + - "| thickness: " + thickness + "| rmin: " + vgi.rmin + - "| rmax: " + vgi.rmax+ - "| xmin: "+vgi.xmin+"| xmax: "+vgi.xmax); - System.out.println(); - } - if(!_useDefaultXPlanes) - { - if(x>0.1) - _matxpl.add(new MaterialXPlane(vgi.ymin,vgi.ymax, vgi.zmin, vgi.zmax, x, thickness)); - } - else - { - _matxpl.add(new MaterialXPlane(vgi.ymin,vgi.ymax, vgi.zmin, vgi.zmax, x, thickness)); - } - } - else if(isCylinder(vgi.rmin, vgi.rmax, vgi.zmin, vgi.zmax)) - { - // Calculate the weighted radius of the elements - double zlen = vgi.zmax - vgi.zmin; - double thickness = vtot / (2. * Math.PI * vgi.weighted_r * zlen * vgi.X0); - + System.out.println("Cylindrical segment of " + pv.getName()); + System.out.println("zmin = " + z1 + "| zmax = " + z2 + "| ravg = " + ravg + "| thickness = " + + thickness); + } + + } // Otherwise this is a non-cylindrical polycone segment + else { + _matpc.add(new MaterialPolyconeSegment(pv, zp1, zp2, thickness, ang)); if (DEBUG) { - System.out.println("Treating as a Cylinder...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + - "| zmax: " + vgi.zmax + "| vtot: " + vtot + - "| thickness: " + thickness + "| rmin: " + vgi.rmin + - "| rmax: " + vgi.rmax); - System.out.println(); - } - - _matcyl.add(new MaterialCylinder(null, vgi.weighted_r, vgi.zmin, vgi.zmax, thickness)); - } - else - { - - double thickness = vtot / (Math.PI * (vgi.rmax * vgi.rmax - vgi.rmin * vgi.rmin) * vgi.X0); - - if (DEBUG) { - System.out.println("x0: " + vgi.X0 + "| zmin: " + vgi.zmin + - "| zmax: " + vgi.zmax + "| vtot: " + vtot + - "| thickness: " + thickness + "| rmin: " + vgi.rmin + - "| rmax: " + vgi.rmax); - System.out.println(); - } - - _matdsk.add(new MaterialDisk(null, vgi.rmin, vgi.rmax, vgi.weighted_z, thickness)); - } - } - } - - private static List<UniquePV> makeUniquePVList(IPhysicalVolumeNavigator nav, IPhysicalVolume trackingVol, - List<String> paths) - { - List<UniquePV> uniqPVs = new ArrayList<UniquePV>(); - for (String path : paths) - { - /** - * Create the path object, prepending tracking volume name, as the paths are relative to Subdetector. - */ - IPhysicalVolumePath pvPath = nav.getPath("/" + trackingVol.getName() + path); - - /** - * Create the UniquePV for MaterialManager. - */ - uniqPVs.add(new UniquePV(pvPath, nav)); - } - return uniqPVs; - } - - public List<MaterialCylinder> getMaterialCylinders() - { - return _matcyl; - } - - public List<MaterialDisk> getMaterialDisks() - { - return _matdsk; - } - public List<MaterialXPlane> getMaterialXPlanes() - { - return _matxpl; - } - - public List<MaterialPolyconeSegment> getMaterialPolyconeSegments() - { - return _matpc; - } - - public static double getRMax() - { - return _rmax; - } - - public static double getZMax() - { - return _zmax; - } - - private boolean isCylinder(double rmin, double rmax, double zmin, double zmax) - { - return (rmax - rmin) * Math.abs(zmax + zmin) < (zmax - zmin) * (rmax + rmin); - } - - private boolean isXPlane(double xmin, double xmax) - { - if(!_useDefaultXPlanes) - { - if(xmax-xmin<0) - return false; //be default xmax is negative, xmin is positive - if(xmax+xmin<50) - return false; //catch short modules... - return (xmax-xmin)<50.0;//5cm... - } - else - { - return (xmax-xmin)<1.0;//1mm - } - } - - public void setTransform(ITransform3D transform) { - _detToTrk = transform; - } - // special handling for Polycone... - private void handlePolycone(IPhysicalVolume pv) - { - Polycone pc = (Polycone)pv.getLogicalVolume().getSolid(); - IMaterial mat = pv.getLogicalVolume().getMaterial(); - - // Loop through each segment - for (int i = 0; i < pc.getNumberOfZPlanes() - 1; i++ ) - { - ZPlane zp1 = pc.getZPlane(i); - ZPlane zp2 = pc.getZPlane(i + 1); - - double z1 = zp1.getZ(); - double z2 = zp2.getZ(); - double vol = Polycone.getSegmentVolume(zp1, zp2); - double zlen = Math.abs(z2 - z1); - double ravg = 0.25 * (zp1.getRMax() + zp1.getRMin() + zp2.getRMax() + zp2.getRMin()); - double ang = Math.atan2(0.5 * (zp1.getRMax() + zp1.getRMin() - zp2.getRMax() - zp2.getRMin()), zlen); - double X0 = 10 * mat.getRadiationLength() / mat.getDensity(); - double thickness = Math.cos(ang) * vol / (2 * Math.PI * ravg * zlen * X0); - - // This is a cylinder - if (zp1.getRMax() == zp2.getRMax() && zp1.getRMin() == zp2.getRMin()) - { - _matcyl.add(new MaterialCylinder(pv, ravg, Math.min(z1, z2), Math.max(z1, z2), thickness)); - if (DEBUG) - { - System.out.println("Cylindrical segment of " + pv.getName()); - System.out.println("zmin = " + z1 + "| zmax = " + z2 + "| ravg = " + ravg + - "| thickness = " + thickness); - } - - } // Otherwise this is a non-cylindrical polycone segment - else - { - _matpc.add(new MaterialPolyconeSegment(pv, zp1, zp2, thickness, ang)); - if (DEBUG) - { System.out.println("Non-Cylindrical segment of " + pv.getName()); System.out.println("ZPlane 1: " + zp1.toString() + "| ZPlane 2: " + zp2.toString() + "| thickness = " + thickness); @@ -601,165 +611,50 @@ } } - /** - * A "struct" holding geometry information about a single physical volume - */ - class VolumeInfo - { - double rmax = 0.0; - double rmin = 1.e10; - double zmin = 1.e10; - double zmax = -1.e10; - //mg 3/14/11 MaterialXPlane info - double ymin = 1.e10; - double ymax=-1.e10; - double xmin = 1.e10; - double xmax=-1.e10; - } - - /** - * A "struct" holding geometry information about lists of physical volumes - */ - class VolumeGroupInfo - { - double rmax = 0.0; - double rmin = 1.e10; - double zmin = 1.e10; - double zmax = -1.e10; - double X0 = 0.0; - double weighted_r = 0.0; - double weighted_z = 0.0; - double vtot_tube_only = 0.; - double vtot = 0.0; - //mg 3/14/11 MaterialXPlane info - double ymin = 1.e10; - double ymax=-1.e10; - double xmin = 1.e10; - double xmax=-1.e10; - double weighted_y = 0.0; - - } - - // This function performs all the calculations on lists of physical volumes - private VolumeGroupInfo performVolumeGroupCalculations(List<UniquePV> volgroup) - { - - VolumeGroupInfo vgi = new VolumeGroupInfo(); - - // If we have a top-level polycone, don't bother doing anything, because - // it'll be handled specially - if (volgroup.size() == 1 && volgroup.get(0).getSolid() instanceof Polycone) - { - return vgi; - } - - // The normal case - double totwgt = 0.0; - if (DEBUG && volgroup.isEmpty()) - { - System.out.println("Empty volume group..."); - } - for (UniquePV pv : volgroup) - { - - // increment total volume - double vol = this.getVolumeOfSolid(pv.getSolid()); - if (pv.getSolid() instanceof Tube) - { - vgi.vtot_tube_only += vol; - } - vgi.vtot += vol; - // calculate weighted R / Z / Radiation Length - VolumeInfo vi = performVolumeCalculations(pv); - IMaterial mat = pv.getPV().getLogicalVolume().getMaterial(); - double matX0 = 10.0 * mat.getRadiationLength() / mat.getDensity(); - double wgt = vol / matX0; - double z0 = pv.getLtoGTransform().getTranslation().z(); - vgi.weighted_r += 0.5 * (vi.rmin + vi.rmax) * wgt; - vgi.weighted_z += z0 * wgt; - totwgt += wgt; - - // grab (z/r)(mins/maxes) - vgi.zmin = Math.min(vi.zmin, vgi.zmin); - vgi.zmax = Math.max(vi.zmax, vgi.zmax); - vgi.rmin = Math.min(vi.rmin, vgi.rmin); - vgi.rmax = Math.max(vi.rmax, vgi.rmax); - //mg 3/14/11 also store y,x information - vgi.ymin = Math.min(vi.ymin, vgi.ymin); - vgi.ymax = Math.max(vi.ymax, vgi.ymax); - double y0 = pv.getLtoGTransform().getTranslation().y(); - vgi.weighted_y += y0 * wgt; - vgi.xmin = Math.min(vi.xmin, vgi.xmin); - vgi.xmax = Math.max(vi.xmax, vgi.xmax); - } - - // finish weighted R/Z calculations + perform X0 calculation - if (totwgt > 0.) - { - vgi.weighted_r /= totwgt; - vgi.weighted_z /= totwgt; - vgi.X0 = vgi.vtot / totwgt; - //mg 3/14/11 also y info - vgi.weighted_y/=totwgt; - } - - return vgi; - } - - private double getVolumeOfSolid(ISolid solid) - { - if (solid_vol_map.containsKey(solid)) - { - return solid_vol_map.get(solid).doubleValue(); - } - else - { - double vol; - try - { - vol = solid.getCubicVolume(); - } - catch (Exception e) - { - vol = 0.0; - } - - solid_vol_map.put(solid, vol); - return vol; - } - - } - - private VolumeInfo performVolumeCalculations(UniquePV pv) - { - - VolumeInfo vi = new VolumeInfo(); - ISolid solid = pv.getSolid(); + private boolean isCylinder(final double rmin, final double rmax, final double zmin, final double zmax) { + return (rmax - rmin) * Math.abs(zmax + zmin) < (zmax - zmin) * (rmax + rmin); + } + + private boolean isXPlane(final double xmin, final double xmax) { + if (!_useDefaultXPlanes) { + if (xmax - xmin < 0) { + return false; // be default xmax is negative, xmin is positive + } + if (xmax + xmin < 50) { + return false; // catch short modules... + } + return xmax - xmin < 50.0;// 5cm... + } else { + return xmax - xmin < 1.0;// 1mm + } + } + + private VolumeInfo performVolumeCalculations(final UniquePV pv) { + + final VolumeInfo vi = new VolumeInfo(); + final ISolid solid = pv.getSolid(); // ASSUMPTION: tube is along z-axis and has center at r = 0 - if (solid instanceof Tube) - { - Tube tube = (Tube)solid; - double z0 = pv.getLtoGTransform().getTranslation().z(); + if (solid instanceof Tube) { + final Tube tube = (Tube) solid; + final double z0 = pv.getLtoGTransform().getTranslation().z(); vi.zmax = z0 + tube.getZHalfLength(); vi.zmin = z0 - tube.getZHalfLength(); vi.rmin = tube.getInnerRadius(); vi.rmax = tube.getOuterRadius(); - } - else if (solid instanceof Box) - { - Box box = (Box)solid; - for (Point3D p : box.getVertices()) - { - Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector()); - if (_detToTrk != null) + } else if (solid instanceof Box) { + final Box box = (Box) solid; + for (final Point3D p : box.getVertices()) { + final Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector()); + if (_detToTrk != null) { _detToTrk.transform(transformed); + } vi.zmin = Math.min(transformed.z(), vi.zmin); vi.zmax = Math.max(transformed.z(), vi.zmax); - double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y()); + final double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y()); vi.rmin = Math.min(vi.rmin, r); vi.rmax = Math.max(vi.rmax, r); - //mg 1/23/12 also store ymin,ymax + // mg 1/23/12 also store ymin,ymax vi.ymin = Math.min(transformed.y(), vi.ymin); vi.ymax = Math.max(transformed.y(), vi.ymax); vi.xmin = Math.min(transformed.x(), vi.xmin); @@ -767,21 +662,19 @@ } - } - else if (solid instanceof Trd) - { - Trd box = (Trd)solid; - for (Point3D p : box.getVertices()) - { - Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector()); - if (_detToTrk != null) + } else if (solid instanceof Trd) { + final Trd box = (Trd) solid; + for (final Point3D p : box.getVertices()) { + final Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector()); + if (_detToTrk != null) { _detToTrk.transform(transformed); + } vi.zmin = Math.min(transformed.z(), vi.zmin); vi.zmax = Math.max(transformed.z(), vi.zmax); - double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y()); + final double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y()); vi.rmin = Math.min(vi.rmin, r); vi.rmax = Math.max(vi.rmax, r); - //mg 3/14/11 also store ymin,ymax + // mg 3/14/11 also store ymin,ymax vi.ymin = Math.min(transformed.y(), vi.ymin); vi.ymax = Math.max(transformed.y(), vi.ymax); vi.xmin = Math.min(transformed.x(), vi.xmin); @@ -793,16 +686,13 @@ // The information here will only be used in case a top-level element // has a subelement that is a Polycone, in which case it'll be // approximated as the smallest possible cylinder. - else if (solid instanceof Polycone) - { - Polycone pc = (Polycone)solid; - List<Polycone.ZPlane> zplanes = pc.getZPlanes(); + else if (solid instanceof Polycone) { + final Polycone pc = (Polycone) solid; + final List<Polycone.ZPlane> zplanes = pc.getZPlanes(); // For now, just take the minimum rmin and rmax of the polycone - for (Polycone.ZPlane z : zplanes) - { - if (z.getRMax() > 0 && z.getRMin() > 0) - { + for (final Polycone.ZPlane z : zplanes) { + if (z.getRMax() > 0 && z.getRMin() > 0) { vi.rmin = Math.min(vi.rmin, z.getRMin()); vi.rmax = vi.rmax > 0. ? Math.min(vi.rmax, z.getRMax()) : z.getRMax(); } @@ -813,9 +703,8 @@ vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size() - 1).getZ(); // check for wrong order - if (vi.zmin > vi.zmax) - { - double temp = vi.zmin; + if (vi.zmin > vi.zmax) { + final double temp = vi.zmin; vi.zmin = vi.zmax; vi.zmax = temp; } @@ -825,104 +714,99 @@ return vi; } - /** - * A UniquePV is a wrapper around IPhysicalVolumePath which provides some convenience methods and caches - * transformations. - */ - static class UniquePV - { - - IPhysicalVolumePath path; - IPhysicalVolumeNavigator nav; - ITransform3D transform = null; - - /** - * Generates a top-level UniquePV. - * - * @param root The top-level IPhysicalVolume - * @param navigator The IPhysicalVolumeNavigator associated with the detector - */ - public UniquePV(IPhysicalVolume root, IPhysicalVolumeNavigator navigator) - { - path = new PhysicalVolumePath(); - nav = navigator; - path.add(root); - } - - /** - * Generates a UniquePV from a path. (Shallow copy of path) - * - * @param path - * @param navigator - */ - public UniquePV(IPhysicalVolumePath path, IPhysicalVolumeNavigator navigator) - { - this.path = path; - nav = navigator; - } - - /** - * Returns the IPhysicalVolume (the last element of the path) - */ - public IPhysicalVolume getPV() - { - return path.getLeafVolume(); - } - - /** - * Creates a UniquePV that is a daughter of the current UniquePV (deep copy made) - * - * @param daughter - * @return - */ - public UniquePV createDaughterUniquePV(IPhysicalVolume daughter) - { - IPhysicalVolumePath np = new PhysicalVolumePath(); - np.addAll(path); - np.add(daughter); - return new UniquePV(np, nav); - } - - /** - * Transforms the given vector from local to global coords. - * - * @param v the untransformed local Hep3Vector - * @return the transformed global Hep3Vector - */ - public Hep3Vector localToGlobal(Hep3Vector v) - { - - return getLtoGTransform().transformed(v); - } - - /** - * Returns the solid associated with the physical volume. - * - * @return - */ - public ISolid getSolid() - { - return this.getPV().getLogicalVolume().getSolid(); - } - - /** - * Returns the local-to-global transform - * - * @return an ITransform3D from local coordinates to global coordinates. - */ - public ITransform3D getLtoGTransform() - { - if (transform == null) - { - transform = nav.getTransform(path); - } - return transform; - } - - @Override - public String toString() - { - return path.toString(); + // This function performs all the calculations on lists of physical volumes + private VolumeGroupInfo performVolumeGroupCalculations(final List<UniquePV> volgroup) { + + final VolumeGroupInfo vgi = new VolumeGroupInfo(); + + // If we have a top-level polycone, don't bother doing anything, because + // it'll be handled specially + if (volgroup.size() == 1 && volgroup.get(0).getSolid() instanceof Polycone) { + return vgi; + } + + // The normal case + double totwgt = 0.0; + if (DEBUG && volgroup.isEmpty()) { + System.out.println("Empty volume group..."); + } + for (final UniquePV pv : volgroup) { + + // increment total volume + final double vol = this.getVolumeOfSolid(pv.getSolid()); + if (pv.getSolid() instanceof Tube) { + vgi.vtot_tube_only += vol; + } + vgi.vtot += vol; + // calculate weighted R / Z / Radiation Length + final VolumeInfo vi = this.performVolumeCalculations(pv); + final IMaterial mat = pv.getPV().getLogicalVolume().getMaterial(); + final double matX0 = 10.0 * mat.getRadiationLength() / mat.getDensity(); + final double wgt = vol / matX0; + final double z0 = pv.getLtoGTransform().getTranslation().z(); + vgi.weighted_r += 0.5 * (vi.rmin + vi.rmax) * wgt; + vgi.weighted_z += z0 * wgt; + totwgt += wgt; + + // grab (z/r)(mins/maxes) + vgi.zmin = Math.min(vi.zmin, vgi.zmin); + vgi.zmax = Math.max(vi.zmax, vgi.zmax); + vgi.rmin = Math.min(vi.rmin, vgi.rmin); + vgi.rmax = Math.max(vi.rmax, vgi.rmax); + // mg 3/14/11 also store y,x information + vgi.ymin = Math.min(vi.ymin, vgi.ymin); + vgi.ymax = Math.max(vi.ymax, vgi.ymax); + final double y0 = pv.getLtoGTransform().getTranslation().y(); + vgi.weighted_y += y0 * wgt; + vgi.xmin = Math.min(vi.xmin, vgi.xmin); + vgi.xmax = Math.max(vi.xmax, vgi.xmax); + } + + // finish weighted R/Z calculations + perform X0 calculation + if (totwgt > 0.) { + vgi.weighted_r /= totwgt; + vgi.weighted_z /= totwgt; + vgi.X0 = vgi.vtot / totwgt; + // mg 3/14/11 also y info + vgi.weighted_y /= totwgt; + } + + return vgi; + } + + /** + * Turn on/off debugging output. + * + * @param debug True if debugging should be enabled; false if not. + */ + public void setDebug(final boolean debug) { + this.DEBUG = debug; + } + + public void setDefaultXPlaneUsage(final boolean useDefault) { + _useDefaultXPlanes = useDefault; + } + + public void setTransform(final ITransform3D transform) { + _detToTrk = transform; + } + + /** + * Setup tracking volume parameters. + * + * @param det The Detector. + */ + private void setupTrackingVolume(final Detector det) { + // Find the envelope of the tracking volume + final ISolid trkvol = det.getTrackingVolume().getLogicalVolume().getSolid(); + if (trkvol instanceof Tube) { + final Tube trktube = (Tube) trkvol; + _rmax = trktube.getOuterRadius(); + _zmax = trktube.getZHalfLength(); + if (DEBUG) { + System.out.println("Ecal radius = " + _rmax); + System.out.println("ECal inner Z = " + _zmax); + } } } } ######################################################################## Use REPLY-ALL to reply to list To unsubscribe from the LCDET-SVN list, click the following link: https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCDET-SVN&A=1