lcsim/src/org/lcsim/contrib/seedtracker
diff -u -r1.9 -r1.10
--- MaterialManager.java 1 Jul 2008 22:29:09 -0000 1.9
+++ MaterialManager.java 1 Jul 2008 23:59:10 -0000 1.10
@@ -14,7 +14,6 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import org.lcsim.detector.DetectorIdentifierHelper;
import org.lcsim.detector.IDetectorElement;
import org.lcsim.detector.identifier.IIdentifier;
@@ -47,8 +46,8 @@
private List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>();
private List<MaterialCylinder> _matcyl = new ArrayList<MaterialCylinder>();
private List<MaterialDisk> _matdsk = new ArrayList<MaterialDisk>();
+ private HashMap<ISolid,Double> solid_vol_map = new HashMap<ISolid,Double>(400);
private double _rmax;
- private CalculationCache cache;
/** Creates a new instance of MaterialManager */
public MaterialManager() {
@@ -56,7 +55,6 @@
public void BuildModel(Detector det) {
- cache = new CalculationCache(det);
// Build the model of tracker material
// Each volume defined in the compact.xml file is modelled as either
// a thin cylinder or disk with a thickness in radiation lengths
@@ -74,7 +72,11 @@
// System.out.println(pvflat.size());
// Calculate the total volume of material, skip this object if 0
- double vtot = TotalVolume(pvflat);
+ VolumeGroupInfo vgi = performVolumeGroupCalculations(pvflat);
+
+ double vtot;
+ if (TUBE_ONLY) vtot = vgi.vtot_tube_only;
+ else vtot = vgi.vtot;
if (pvtree.getLogicalVolume().getSolid() instanceof Polycone){
@@ -85,44 +87,39 @@
if (vtot > 0.) {
// Calculate the average radiation length for this volume
- double X0 = RadiationLength(pvflat);
+
// Determine if this volume should be modeled as barrel or disk
- if (isCylinder(pvflat)) {
+ if (isCylinder(vgi.rmin,vgi.rmax,vgi.zmin,vgi.zmax)) {
// Calculate the weighted radius of the elements
- double rwgt = WeightedRadius(pvflat);
- double zmin = zmin(pvflat);
- double zmax = zmax(pvflat);
- double zlen = zmax - zmin;
- double thickness = vtot / (2. * Math.PI * rwgt * zlen * X0);
+ double zlen = vgi.zmax - vgi.zmin;
+ double thickness = vtot / (2. * Math.PI * vgi.weighted_r * zlen * vgi.X0);
if (DEBUG){
System.out.println(pvtree.getName());
- System.out.println("x0: "+X0 + "| zmin: "+zmin + "| zmax: "+zmax + "| vtot: "+vtot + "| thickness: "+thickness +
- "| rmin: "+(rmin(pvflat)) + "| rmax: "+rmax(pvflat));
+ 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();
}
- _matcyl.add(new MaterialCylinder(pvtree, rwgt, zmin, zmax, thickness));
+ _matcyl.add(new MaterialCylinder(pvtree, vgi.weighted_r, vgi.zmin, vgi.zmax, thickness));
} else {
- double zwgt = WeightedZ(pvflat);
- double rmin = rmin(pvflat);
- double rmax = rmax(pvflat);
- double thickness = vtot / (Math.PI * (rmax*rmax - rmin*rmin) * X0);
+
+ double thickness = vtot / (Math.PI * (vgi.rmax*vgi.rmax - vgi.rmin*vgi.rmin) * vgi.X0);
if (DEBUG){
System.out.println(pvtree.getName());
- System.out.println("x0: "+X0 + "| zmin: "+zmin(pvflat) + "| zmax: "+zmax(pvflat) + "| vtot: "+vtot + "| thickness: "+thickness +
- "| rmin: "+rmin + "| rmax: "+rmax);
+ 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(pvtree, rmin, rmax, zwgt, thickness));
+ _matdsk.add(new MaterialDisk(pvtree, vgi.rmin, vgi.rmax, vgi.weighted_z, thickness));
}
}
}
- if(DEBUG) cache.printSizeInfo();
- cache.clear(); // clear cache, so stuff doesn't get held in memory.
+
+ solid_vol_map.clear();
// Find the outer radius of the tracking volume
// First loop over all the subdetector elements
@@ -198,48 +195,10 @@
}
- //Tube only for now... (note that the problem with top-level polycones should no longer exist)
- private double TotalVolume(List<UniquePV> pvlist) {
- if (TUBE_ONLY) return cache.getVolumeGroupCalculations(pvlist).vtot_tube_only;
- return cache.getVolumeGroupCalculations(pvlist).vtot;
- }
-
- private double RadiationLength(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).X0;
- }
-
- private double rmin(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).rmin;
- }
-
- private double rmax(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).rmax;
- }
-
- private double zmin(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).zmin;
- }
-
- private double zmax(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).zmax;
- }
-
- private boolean isCylinder(List<UniquePV> pvlist) {
- double rmin = rmin(pvlist);
- double rmax = rmax(pvlist);
- double zmin = zmin(pvlist);
- double zmax = zmax(pvlist);
+ private boolean isCylinder(double rmin, double rmax, double zmin, double zmax) {
return (rmax - rmin) * Math.abs(zmax + zmin) < (zmax - zmin) * (rmax + rmin);
}
- private double WeightedRadius(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).weighted_r;
- }
-
- private double WeightedZ(List<UniquePV> pvlist) {
- return cache.getVolumeGroupCalculations(pvlist).weighted_z;
- }
-
// special handling for Polycone...
private void handlePolycone(IPhysicalVolume pv){
Polycone pc = (Polycone) pv.getLogicalVolume().getSolid();
@@ -306,238 +265,129 @@
double vtot = 0.0;
}
- /**
- * A class that calculates / caches geometry information about physical volumes.
- */
- class CalculationCache {
- Map<UniquePV,VolumeInfo> pv_map;
- Map<List<UniquePV>,VolumeGroupInfo> pv_group_map;
- Map<ISolid,Double> solid_vol_map;
- private final float load_factor = 0.75f; //(default)
-
- /**
- * Constructor. The detector is used to help determine the initial values of the hashmaps.
- * @param det
- */
- public CalculationCache(Detector det){
- int pv_map_size;
- int pv_group_map_size;
- int solid_vol_map_size;
-
-
- //Resizing HashMaps is slow, so we use some magic numbers to speed things up a little
- if(det.getName().indexOf("planar")>-1){ //these values should work well for the current planar model
- if(DEBUG) System.out.println("Using initial map values for planar detector");
- pv_map_size = (int) (130000/load_factor);
- pv_group_map_size = (int) (120/load_factor);
- solid_vol_map_size = (int) (1300/load_factor);
- } else { //these values should work pretty well for sid01
- pv_map_size = (int) (500/load_factor);
- pv_group_map_size = (int) (200/load_factor);
- solid_vol_map_size = (int) (250/load_factor);
- }
-
- pv_map = new HashMap<UniquePV,VolumeInfo>(pv_map_size,load_factor);
- pv_group_map = new HashMap<List<UniquePV>,VolumeGroupInfo>(pv_group_map_size,load_factor);
- solid_vol_map = new HashMap<ISolid,Double>(solid_vol_map_size, load_factor);
-
-
- }
-
- //clear function... after we've created the MaterialCylinders and
- //material disks, we don't want to have this information cached anymore
- //because it may sit around in RAM (not sure if the GC is smart enough
- //to clear it by itself).
-
- /**
- * Releases the resources associated with the cache.
- */
- public void clear(){
- pv_map.clear();
- pv_group_map.clear();
- solid_vol_map.clear();
- System.gc();
+
+ //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;
}
-
- /**
- * Prints out the current number of objects inside the cache's data structure
- */
- public void printSizeInfo(){
- System.out.println("pv_map size: "+pv_map.size());
- System.out.println("pv_group_map size: "+pv_group_map.size());
- System.out.println("solid_vol_map size: "+solid_vol_map.size());
+
+ //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);
+
}
-
- /**
- * Returns a VolumeGroupInfo object containing geometry and radiation-lenght
- * information about the target collection of physical volumes.
- *
- * If a single-element collection consisting of a polycone is passed,
- * no calculation is performed (top-level polycones are handled separately in
- * MaterialManager).
- *
- * @param volgroup A list of UniquePVs
- * @return A VolumeGroupInfo object
- */
- public VolumeGroupInfo getVolumeGroupCalculations(List<UniquePV> volgroup) {
- if (pv_group_map.containsKey(volgroup)) {
- // System.out.println("Using cached calculation");
- return pv_group_map.get(volgroup);
- }
- else return performVolumeGroupCalculations(volgroup);
+
+ //finish weighted R/Z calculations + perform X0 calculation
+ if (totwgt > 0.) {
+ vgi.weighted_r /= totwgt;
+ vgi.weighted_z /= totwgt;
+ vgi.X0 = vgi.vtot / totwgt;
+ }
+
+ return vgi;
+ }
+
+ private double getVolumeOfSolid(ISolid solid){
+ if (solid_vol_map.containsKey(solid)){
+ return solid_vol_map.get(solid).doubleValue();
}
-
- //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 = this.getVolumeCalculations(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);
-
- }
-
- //finish weighted R/Z calculations + perform X0 calculation
- if (totwgt > 0.) {
- vgi.weighted_r /= totwgt;
- vgi.weighted_z /= totwgt;
- vgi.X0 = vgi.vtot / totwgt;
- }
-
-
- pv_group_map.put(volgroup,vgi);
- return vgi;
+
+ else {
+ double vol;
+ try{ vol = solid.getCubicVolume(); }
+ catch(Exception e) { vol = 0.0; }
+ solid_vol_map.put(solid,vol);
+ return vol;
}
-
- /**
- * Returns the cubic volume of the specified solid. Caches after first
- * call. If solid.getCubicVolume() throws an exception, 0.0 is returned.
- * @param solid The target ISolid
- * @return a double corresponding to the cubic volume in mm^3
- */
- public 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();
+
+ //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();
+ vi.zmax = z0 + tube.getZHalfLength();
+ vi.zmin = z0 - tube.getZHalfLength();
+ vi.rmin = tube.getInnerRadius();
+ vi.rmax = tube.getOuterRadius();
}
-
- /**
- * Returns a VolumeInfo object containing information about the target
- * UniquePV (rmin, rmax, zmin, zmax). The value is cached after the first
- * call.
- *
- * @param pv The target UniquePV
- * @return VolumeInfo containing information about the geometry of the PV.
- */
- public VolumeInfo getVolumeCalculations(UniquePV pv){
-
- // check if the result has been cached already
- if (pv_map.containsKey(pv)) {
- //System.out.println("Using cached calculation");
- return pv_map.get(pv);
+
+ else if (solid instanceof Box) {
+ Box box = (Box) solid;
+ for (Point3D p : box.getVertices()){
+ Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector());
+ 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());
+ vi.rmin = Math.min(vi.rmin, r);
+ vi.rmax = Math.max(vi.rmax, r);
}
- //otherwise calculate them...
- else return performVolumeCalculations(pv);
-
}
-
- private VolumeInfo performVolumeCalculations(UniquePV pv){
-
- VolumeInfo vi = new VolumeInfo();
- 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();
- vi.zmax = z0 + tube.getZHalfLength();
- vi.zmin = z0 - tube.getZHalfLength();
- vi.rmin = tube.getInnerRadius();
- vi.rmax = tube.getOuterRadius();
- }
+ //Note: this information will NOT be used most of the time...
+ // Polycones that are top-level elements (e.g. the beampipe) are
+ // handled specially (since the radiation length is a function of z).
+ // 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 Box) {
- Box box = (Box) solid;
- for (Point3D p : box.getVertices()){
- Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector());
- 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());
- vi.rmin = Math.min(vi.rmin, r);
- vi.rmax = Math.max(vi.rmax, r);
+ //For now, just take the minimum rmin and rmax of the polycone
+ for (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();
}
}
-
- //Note: this information will NOT be used most of the time...
- // Polycones that are top-level elements (e.g. the beampipe) are
- // handled specially (since the radiation length is a function of z).
- // 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();
-
- //For now, just take the minimum rmin and rmax of the polycone
- for (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();
- }
- }
- vi.zmin = pc.getZPlanes().get(0).getZ();
- vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size()-1).getZ();
-
- //check for wrong order
- if (vi.zmin > vi.zmax) {
- double temp = vi.zmin;
- vi.zmin = vi.zmax;
- vi.zmax = temp;
- }
+ vi.zmin = pc.getZPlanes().get(0).getZ();
+ vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size()-1).getZ();
+
+ //check for wrong order
+ if (vi.zmin > vi.zmax) {
+ double temp = vi.zmin;
+ vi.zmin = vi.zmax;
+ vi.zmax = temp;
}
-
- pv_map.put(pv,vi);
- return vi;
}
+
+ return vi;
}
+
/**
* A UniquePV is a wrapper around IPhysicalVolumePath which provides