Commit in lcsim/src/org/lcsim/contrib/seedtracker on MAIN
MaterialManager.java+127-2771.9 -> 1.10
CD - big MaterialManager update... continued... (removed some unnecessary caching by refactoring)

lcsim/src/org/lcsim/contrib/seedtracker
MaterialManager.java 1.9 -> 1.10
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 
CVSspam 0.2.8