1 package org.lcsim.recon.tracking.seedtracker;
2
3 import hep.physics.vec.Hep3Vector;
4
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 import org.lcsim.detector.IDetectorElement;
11 import org.lcsim.detector.IPhysicalVolume;
12 import org.lcsim.detector.IPhysicalVolumeNavigator;
13 import org.lcsim.detector.IPhysicalVolumePath;
14 import org.lcsim.detector.ITransform3D;
15 import org.lcsim.detector.PhysicalVolumeNavigator;
16 import org.lcsim.detector.PhysicalVolumeNavigatorStore;
17 import org.lcsim.detector.PhysicalVolumePath;
18 import org.lcsim.detector.material.IMaterial;
19 import org.lcsim.detector.solids.Box;
20 import org.lcsim.detector.solids.ISolid;
21 import org.lcsim.detector.solids.Point3D;
22 import org.lcsim.detector.solids.Polycone;
23 import org.lcsim.detector.solids.Polycone.ZPlane;
24 import org.lcsim.detector.solids.Trd;
25 import org.lcsim.detector.solids.Tube;
26 import org.lcsim.geometry.Detector;
27 import org.lcsim.geometry.Subdetector;
28 import org.lcsim.geometry.subdetector.DiskTracker;
29 import org.lcsim.geometry.subdetector.MultiLayerTracker;
30 import org.lcsim.geometry.subdetector.PolyconeSupport;
31 import org.lcsim.geometry.subdetector.SiTrackerBarrel;
32 import org.lcsim.geometry.subdetector.SiTrackerEndcap;
33 import org.lcsim.geometry.subdetector.SiTrackerEndcap2;
34 import org.lcsim.geometry.subdetector.SiTrackerFixedTarget2;
35 import org.lcsim.geometry.subdetector.SiTrackerSpectrometer;
36
37
38
39
40
41
42
43
44
45
46 public class MaterialManager {
47
48
49
50
51
52 public static final class BarrelLayerVolumeGroup implements SubdetectorVolumeGrouper {
53
54 @Override
55 public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
56 final List<List<String>> pathGroups = new ArrayList<List<String>>();
57 for (final IDetectorElement layer : subdet.getDetectorElement().getChildren()) {
58 final List<String> layerPaths = new ArrayList<String>();
59 final String path = "";
60 PhysicalVolumeNavigator.getLeafPaths(layerPaths, layer.getGeometry().getPhysicalVolume(), path);
61 pathGroups.add(layerPaths);
62 }
63 return pathGroups;
64 }
65 }
66
67
68
69
70 public static final class EndcapVolumeGrouper implements SubdetectorVolumeGrouper {
71
72 @Override
73 public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
74 final List<List<String>> pathGroups = new ArrayList<List<String>>();
75
76 for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) {
77
78 for (final IDetectorElement layer : endcaps.getChildren()) {
79 final List<String> layerPaths = new ArrayList<String>();
80 final String path = "";
81 PhysicalVolumeNavigator.getLeafPaths(layerPaths, layer.getGeometry().getPhysicalVolume(), path);
82 pathGroups.add(layerPaths);
83 }
84 }
85 return pathGroups;
86 }
87
88 }
89
90
91
92
93 public static final class PolyconeSupportVolumeGrouper implements SubdetectorVolumeGrouper {
94
95 @Override
96 public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
97 final List<List<String>> pathGroups = new ArrayList<List<String>>();
98 final String path = "";
99 final List<String> supportPath = new ArrayList<String>();
100 final IPhysicalVolume supportPV = subdet.getDetectorElement().getChildren().get(0).getGeometry()
101 .getPhysicalVolume();
102 PhysicalVolumeNavigator.getLeafPaths(supportPath, supportPV, path);
103 pathGroups.add(supportPath);
104 return pathGroups;
105 }
106 }
107
108
109
110
111 public static final class SiTrackerEndap2VolumeGrouper implements SubdetectorVolumeGrouper {
112
113 @Override
114 public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
115 final List<List<String>> pathGroups = new ArrayList<List<String>>();
116
117 for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) {
118
119 for (final IDetectorElement layer : endcaps.getChildren()) {
120 final List<String> modulePaths = new ArrayList<String>();
121
122
123 for (final IDetectorElement module : layer.getChildren()) {
124 final String path = "";
125 PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(),
126 path);
127 }
128
129
130
131
132
133
134 pathGroups.add(modulePaths);
135 }
136 }
137 return pathGroups;
138 }
139 }
140
141
142
143
144 public static final class SiTrackerFixedTarget2VolumeGrouper implements SubdetectorVolumeGrouper {
145
146 @Override
147 public List<List<String>> getPathGroups(final Subdetector subdet, final IPhysicalVolume topVol) {
148 final List<List<String>> pathGroups = new ArrayList<List<String>>();
149
150 for (final IDetectorElement endcaps : subdet.getDetectorElement().getChildren()) {
151
152 for (final IDetectorElement layer : endcaps.getChildren()) {
153 final List<String> modulePaths = new ArrayList<String>();
154
155
156
157 for (final IDetectorElement module : layer.getChildren()) {
158 final String path = "";
159 PhysicalVolumeNavigator.getLeafPaths(modulePaths, module.getGeometry().getPhysicalVolume(),
160 path);
161 }
162
163 pathGroups.add(modulePaths);
164 }
165 }
166 return pathGroups;
167 }
168 }
169
170
171
172
173 public interface SubdetectorVolumeGrouper {
174
175 List<List<String>> getPathGroups(Subdetector subdet, IPhysicalVolume topVol);
176 }
177
178
179
180
181
182 static class UniquePV {
183
184 IPhysicalVolumeNavigator nav;
185 IPhysicalVolumePath path;
186 ITransform3D transform = null;
187
188
189
190
191
192
193
194 public UniquePV(final IPhysicalVolume root, final IPhysicalVolumeNavigator navigator) {
195 path = new PhysicalVolumePath();
196 nav = navigator;
197 path.add(root);
198 }
199
200
201
202
203
204
205
206 public UniquePV(final IPhysicalVolumePath path, final IPhysicalVolumeNavigator navigator) {
207 this.path = path;
208 nav = navigator;
209 }
210
211
212
213
214
215
216
217 public UniquePV createDaughterUniquePV(final IPhysicalVolume daughter) {
218 final IPhysicalVolumePath np = new PhysicalVolumePath();
219 np.addAll(path);
220 np.add(daughter);
221 return new UniquePV(np, nav);
222 }
223
224
225
226
227
228
229 public ITransform3D getLtoGTransform() {
230 if (transform == null) {
231 transform = nav.getTransform(path);
232 }
233 return transform;
234 }
235
236
237
238
239 public IPhysicalVolume getPV() {
240 return path.getLeafVolume();
241 }
242
243
244
245
246
247
248 public ISolid getSolid() {
249 return this.getPV().getLogicalVolume().getSolid();
250 }
251
252
253
254
255
256
257
258 public Hep3Vector localToGlobal(final Hep3Vector v) {
259
260 return this.getLtoGTransform().transformed(v);
261 }
262
263 @Override
264 public String toString() {
265 return path.toString();
266 }
267 }
268
269
270
271
272 class VolumeGroupInfo {
273
274 double rmax = 0.0;
275 double rmin = 1.e10;
276 double vtot = 0.0;
277 double vtot_tube_only = 0.;
278 double weighted_r = 0.0;
279 double weighted_y = 0.0;
280 double weighted_z = 0.0;
281 double X0 = 0.0;
282 double xmax = -1.e10;
283 double xmin = 1.e10;
284 double ymax = -1.e10;
285
286 double ymin = 1.e10;
287 double zmax = -1.e10;
288 double zmin = 1.e10;
289
290 }
291
292
293
294
295 class VolumeInfo {
296
297 double rmax = 0.0;
298 double rmin = 1.e10;
299 double xmax = -1.e10;
300 double xmin = 1.e10;
301 double ymax = -1.e10;
302
303 double ymin = 1.e10;
304 double zmax = -1.e10;
305 double zmin = 1.e10;
306 }
307
308 private static ITransform3D _detToTrk;
309 private static double _rmax;
310
311 private static double _zmax = 1800.;
312
313 private static final boolean TUBE_ONLY = false;
314
315 public static double getRMax() {
316 return _rmax;
317 }
318
319 public static double getZMax() {
320 return _zmax;
321 }
322
323 private static List<UniquePV> makeUniquePVList(final IPhysicalVolumeNavigator nav,
324 final IPhysicalVolume trackingVol, final List<String> paths) {
325 final List<UniquePV> uniqPVs = new ArrayList<UniquePV>();
326 for (final String path : paths) {
327
328
329
330 final IPhysicalVolumePath pvPath = nav.getPath("/" + trackingVol.getName() + path);
331
332
333
334
335 uniqPVs.add(new UniquePV(pvPath, nav));
336 }
337 return uniqPVs;
338 }
339
340 private final List<MaterialCylinder> _matcyl = new ArrayList<MaterialCylinder>();
341
342 private final List<MaterialDisk> _matdsk = new ArrayList<MaterialDisk>();
343
344
345 private final List<MaterialPolyconeSegment> _matpc = new ArrayList<MaterialPolyconeSegment>();
346
347 private final List<MaterialXPlane> _matxpl = new ArrayList<MaterialXPlane>();
348
349 private boolean _useDefaultXPlanes = true;
350
351
352 protected boolean DEBUG = false;
353
354 private final HashMap<ISolid, Double> solid_vol_map = new HashMap<ISolid, Double>(400);
355
356
357
358
359 protected final Map<Class, SubdetectorVolumeGrouper> subdetGroups = new HashMap<Class, SubdetectorVolumeGrouper>();
360
361
362
363
364 public MaterialManager() {
365
366 final SubdetectorVolumeGrouper barrelGrouper = new BarrelLayerVolumeGroup();
367 subdetGroups.put(SiTrackerBarrel.class, barrelGrouper);
368 subdetGroups.put(MultiLayerTracker.class, barrelGrouper);
369
370
371 final SubdetectorVolumeGrouper endcapGrouper = new EndcapVolumeGrouper();
372 subdetGroups.put(SiTrackerEndcap.class, endcapGrouper);
373 subdetGroups.put(DiskTracker.class, endcapGrouper);
374
375
376 final SubdetectorVolumeGrouper endcap2Grouper = new SiTrackerEndap2VolumeGrouper();
377 subdetGroups.put(SiTrackerEndcap2.class, endcap2Grouper);
378 subdetGroups.put(SiTrackerSpectrometer.class, endcap2Grouper);
379
380
381 subdetGroups.put(SiTrackerFixedTarget2.class, new SiTrackerFixedTarget2VolumeGrouper());
382
383
384 subdetGroups.put(PolyconeSupport.class, new PolyconeSupportVolumeGrouper());
385 }
386
387
388
389
390
391
392
393 private void addVolumeGroupInfo(final List<UniquePV> uniqPVs, final VolumeGroupInfo vgi) {
394 double vtot;
395 if (TUBE_ONLY) {
396 vtot = vgi.vtot_tube_only;
397 } else {
398 vtot = vgi.vtot;
399 }
400
401
402 if (uniqPVs.get(0).getPV().getLogicalVolume().getSolid() instanceof Polycone) {
403 this.handlePolycone(uniqPVs.get(0).getPV());
404 }
405
406 if (vtot > 0.) {
407
408
409
410
411 if (this.isXPlane(vgi.xmin, vgi.xmax)) {
412
413 final double zlen = vgi.zmax - vgi.zmin;
414 final double ylen = vgi.ymax - vgi.ymin;
415 final double thickness = vtot / (ylen * zlen * vgi.X0);
416 final double x = (vgi.xmax + vgi.xmin) / 2;
417
418 if (DEBUG) {
419 System.out.println("Treating as a XPlane...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: "
420 + vgi.zmax + "| vtot: " + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin
421 + "| rmax: " + vgi.rmax + "| xmin: " + vgi.xmin + "| xmax: " + vgi.xmax);
422 System.out.println();
423 }
424 if (!_useDefaultXPlanes) {
425 if (x > 0.1) {
426 _matxpl.add(new MaterialXPlane(vgi.ymin, vgi.ymax, vgi.zmin, vgi.zmax, x, thickness));
427 }
428 } else {
429 _matxpl.add(new MaterialXPlane(vgi.ymin, vgi.ymax, vgi.zmin, vgi.zmax, x, thickness));
430 }
431 } else if (this.isCylinder(vgi.rmin, vgi.rmax, vgi.zmin, vgi.zmax)) {
432
433 final double zlen = vgi.zmax - vgi.zmin;
434 final double thickness = vtot / (2. * Math.PI * vgi.weighted_r * zlen * vgi.X0);
435
436 if (DEBUG) {
437 System.out.println("Treating as a Cylinder...x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: "
438 + vgi.zmax + "| vtot: " + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin
439 + "| rmax: " + vgi.rmax);
440 System.out.println();
441 }
442
443 _matcyl.add(new MaterialCylinder(null, vgi.weighted_r, vgi.zmin, vgi.zmax, thickness));
444 } else {
445
446 final double thickness = vtot / (Math.PI * (vgi.rmax * vgi.rmax - vgi.rmin * vgi.rmin) * vgi.X0);
447
448 if (DEBUG) {
449 System.out.println("x0: " + vgi.X0 + "| zmin: " + vgi.zmin + "| zmax: " + vgi.zmax + "| vtot: "
450 + vtot + "| thickness: " + thickness + "| rmin: " + vgi.rmin + "| rmax: " + vgi.rmax);
451 System.out.println();
452 }
453
454 _matdsk.add(new MaterialDisk(null, vgi.rmin, vgi.rmax, vgi.weighted_z, thickness));
455 }
456 }
457 }
458
459
460
461
462 public void buildModel(final Detector det) {
463
464 final IPhysicalVolumeNavigator nav = PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator();
465
466
467 final IPhysicalVolume trackingVol = det.getTrackingVolume();
468
469
470 for (final Subdetector subdet : det.getSubdetectorList()) {
471
472 if (subdet.isInsideTrackingVolume()) {
473 if (DEBUG) {
474 System.out.println();
475 System.out.println(">>>> " + subdet.getName() + " >>>>");
476 }
477
478
479 final SubdetectorVolumeGrouper subdetGrouper = subdetGroups.get(subdet.getClass());
480
481
482 if (subdetGrouper == null) {
483 System.out.println("WARNING: Can't handle Subdetector of type <"
484 + subdet.getClass().getCanonicalName() + ">.");
485 } else {
486 if (DEBUG) {
487 System.out.println("Found VolumeGrouper <" + subdetGrouper.getClass().getName() + ">.");
488 }
489
490
491 final List<List<String>> pathGroups = subdetGrouper.getPathGroups(subdet, trackingVol);
492
493 if (DEBUG) {
494 System.out.println("Got " + pathGroups.size() + " path groups.");
495 }
496
497
498 for (final List<String> pathGroup : pathGroups) {
499 if (DEBUG) {
500 System.out.println("Adding next " + pathGroup.size() + " paths.");
501 }
502
503
504 final List<UniquePV> uniqPVs = makeUniquePVList(nav, trackingVol, pathGroup);
505
506
507 final VolumeGroupInfo vgi = this.performVolumeGroupCalculations(uniqPVs);
508
509
510 if (DEBUG) {
511 System.out.println("VolumeGroupInfo ...");
512 System.out.println(" rmax = " + vgi.rmax);
513 System.out.println(" rmin = " + vgi.rmin);
514 System.out.println(" xmin = " + vgi.xmin);
515 System.out.println(" xmax = " + vgi.xmax);
516 System.out.println(" ymin = " + vgi.ymin);
517 System.out.println(" ymax = " + vgi.ymax);
518 System.out.println(" zmin = " + vgi.zmin);
519 System.out.println(" zmax = " + vgi.zmax);
520 System.out.println(" X0 = " + vgi.X0);
521 System.out.println(" weighted_r = " + vgi.weighted_r);
522 System.out.println(" weighted_z = " + vgi.weighted_z);
523 System.out.println(" weighted_z = " + vgi.weighted_y);
524 System.out.println(" vtot_tube_only = " + vgi.vtot_tube_only);
525 System.out.println(" vtot = " + vgi.vtot);
526 }
527
528
529
530 this.addVolumeGroupInfo(uniqPVs, vgi);
531 }
532 }
533 }
534 }
535
536
537 this.setupTrackingVolume(det);
538 }
539
540 public List<MaterialCylinder> getMaterialCylinders() {
541 return _matcyl;
542 }
543
544 public List<MaterialDisk> getMaterialDisks() {
545 return _matdsk;
546 }
547
548 public List<MaterialPolyconeSegment> getMaterialPolyconeSegments() {
549 return _matpc;
550 }
551
552 public List<MaterialXPlane> getMaterialXPlanes() {
553 return _matxpl;
554 }
555
556 private double getVolumeOfSolid(final ISolid solid) {
557 if (solid_vol_map.containsKey(solid)) {
558 return solid_vol_map.get(solid).doubleValue();
559 } else {
560 double vol;
561 try {
562 vol = solid.getCubicVolume();
563 } catch (final Exception e) {
564 vol = 0.0;
565 }
566
567 solid_vol_map.put(solid, vol);
568 return vol;
569 }
570
571 }
572
573
574 private void handlePolycone(final IPhysicalVolume pv) {
575 final Polycone pc = (Polycone) pv.getLogicalVolume().getSolid();
576 final IMaterial mat = pv.getLogicalVolume().getMaterial();
577
578
579 for (int i = 0; i < pc.getNumberOfZPlanes() - 1; i++) {
580 final ZPlane zp1 = pc.getZPlane(i);
581 final ZPlane zp2 = pc.getZPlane(i + 1);
582
583 final double z1 = zp1.getZ();
584 final double z2 = zp2.getZ();
585 final double vol = Polycone.getSegmentVolume(zp1, zp2);
586 final double zlen = Math.abs(z2 - z1);
587 final double ravg = 0.25 * (zp1.getRMax() + zp1.getRMin() + zp2.getRMax() + zp2.getRMin());
588 final double ang = Math.atan2(0.5 * (zp1.getRMax() + zp1.getRMin() - zp2.getRMax() - zp2.getRMin()), zlen);
589 final double X0 = 10 * mat.getRadiationLength() / mat.getDensity();
590 final double thickness = Math.cos(ang) * vol / (2 * Math.PI * ravg * zlen * X0);
591
592
593 if (zp1.getRMax() == zp2.getRMax() && zp1.getRMin() == zp2.getRMin()) {
594 _matcyl.add(new MaterialCylinder(pv, ravg, Math.min(z1, z2), Math.max(z1, z2), thickness));
595 if (DEBUG) {
596 System.out.println("Cylindrical segment of " + pv.getName());
597 System.out.println("zmin = " + z1 + "| zmax = " + z2 + "| ravg = " + ravg + "| thickness = "
598 + thickness);
599 }
600
601 }
602 else {
603 _matpc.add(new MaterialPolyconeSegment(pv, zp1, zp2, thickness, ang));
604 if (DEBUG) {
605 System.out.println("Non-Cylindrical segment of " + pv.getName());
606 System.out.println("ZPlane 1: " + zp1.toString() + "| ZPlane 2: " + zp2.toString()
607 + "| thickness = " + thickness);
608 }
609
610 }
611 }
612 }
613
614 private boolean isCylinder(final double rmin, final double rmax, final double zmin, final double zmax) {
615 return (rmax - rmin) * Math.abs(zmax + zmin) < (zmax - zmin) * (rmax + rmin);
616 }
617
618 private boolean isXPlane(final double xmin, final double xmax) {
619 if (!_useDefaultXPlanes) {
620 if (xmax - xmin < 0) {
621 return false;
622 }
623 if (xmax + xmin < 50) {
624 return false;
625 }
626 return xmax - xmin < 50.0;
627 } else {
628 return xmax - xmin < 1.0;
629 }
630 }
631
632 private VolumeInfo performVolumeCalculations(final UniquePV pv) {
633
634 final VolumeInfo vi = new VolumeInfo();
635 final ISolid solid = pv.getSolid();
636
637
638 if (solid instanceof Tube) {
639 final Tube tube = (Tube) solid;
640 final double z0 = pv.getLtoGTransform().getTranslation().z();
641 vi.zmax = z0 + tube.getZHalfLength();
642 vi.zmin = z0 - tube.getZHalfLength();
643 vi.rmin = tube.getInnerRadius();
644 vi.rmax = tube.getOuterRadius();
645 } else if (solid instanceof Box) {
646 final Box box = (Box) solid;
647 for (final Point3D p : box.getVertices()) {
648 final Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector());
649 if (_detToTrk != null) {
650 _detToTrk.transform(transformed);
651 }
652 vi.zmin = Math.min(transformed.z(), vi.zmin);
653 vi.zmax = Math.max(transformed.z(), vi.zmax);
654 final double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y());
655 vi.rmin = Math.min(vi.rmin, r);
656 vi.rmax = Math.max(vi.rmax, r);
657
658 vi.ymin = Math.min(transformed.y(), vi.ymin);
659 vi.ymax = Math.max(transformed.y(), vi.ymax);
660 vi.xmin = Math.min(transformed.x(), vi.xmin);
661 vi.xmax = Math.max(transformed.x(), vi.xmax);
662
663 }
664
665 } else if (solid instanceof Trd) {
666 final Trd box = (Trd) solid;
667 for (final Point3D p : box.getVertices()) {
668 final Hep3Vector transformed = pv.localToGlobal(p.getHep3Vector());
669 if (_detToTrk != null) {
670 _detToTrk.transform(transformed);
671 }
672 vi.zmin = Math.min(transformed.z(), vi.zmin);
673 vi.zmax = Math.max(transformed.z(), vi.zmax);
674 final double r = Math.sqrt(transformed.x() * transformed.x() + transformed.y() * transformed.y());
675 vi.rmin = Math.min(vi.rmin, r);
676 vi.rmax = Math.max(vi.rmax, r);
677
678 vi.ymin = Math.min(transformed.y(), vi.ymin);
679 vi.ymax = Math.max(transformed.y(), vi.ymax);
680 vi.xmin = Math.min(transformed.x(), vi.xmin);
681 vi.xmax = Math.max(transformed.x(), vi.xmax);
682 }
683 }
684
685
686
687
688
689 else if (solid instanceof Polycone) {
690 final Polycone pc = (Polycone) solid;
691 final List<Polycone.ZPlane> zplanes = pc.getZPlanes();
692
693
694 for (final Polycone.ZPlane z : zplanes) {
695 if (z.getRMax() > 0 && z.getRMin() > 0) {
696 vi.rmin = Math.min(vi.rmin, z.getRMin());
697 vi.rmax = vi.rmax > 0. ? Math.min(vi.rmax, z.getRMax()) : z.getRMax();
698 }
699
700 }
701
702 vi.zmin = pc.getZPlanes().get(0).getZ();
703 vi.zmax = pc.getZPlanes().get(pc.getZPlanes().size() - 1).getZ();
704
705
706 if (vi.zmin > vi.zmax) {
707 final double temp = vi.zmin;
708 vi.zmin = vi.zmax;
709 vi.zmax = temp;
710 }
711
712 }
713
714 return vi;
715 }
716
717
718 private VolumeGroupInfo performVolumeGroupCalculations(final List<UniquePV> volgroup) {
719
720 final VolumeGroupInfo vgi = new VolumeGroupInfo();
721
722
723
724 if (volgroup.size() == 1 && volgroup.get(0).getSolid() instanceof Polycone) {
725 return vgi;
726 }
727
728
729 double totwgt = 0.0;
730 if (DEBUG && volgroup.isEmpty()) {
731 System.out.println("Empty volume group...");
732 }
733 for (final UniquePV pv : volgroup) {
734
735
736 final double vol = this.getVolumeOfSolid(pv.getSolid());
737 if (pv.getSolid() instanceof Tube) {
738 vgi.vtot_tube_only += vol;
739 }
740 vgi.vtot += vol;
741
742 final VolumeInfo vi = this.performVolumeCalculations(pv);
743 final IMaterial mat = pv.getPV().getLogicalVolume().getMaterial();
744 final double matX0 = 10.0 * mat.getRadiationLength() / mat.getDensity();
745 final double wgt = vol / matX0;
746 final double z0 = pv.getLtoGTransform().getTranslation().z();
747 vgi.weighted_r += 0.5 * (vi.rmin + vi.rmax) * wgt;
748 vgi.weighted_z += z0 * wgt;
749 totwgt += wgt;
750
751
752 vgi.zmin = Math.min(vi.zmin, vgi.zmin);
753 vgi.zmax = Math.max(vi.zmax, vgi.zmax);
754 vgi.rmin = Math.min(vi.rmin, vgi.rmin);
755 vgi.rmax = Math.max(vi.rmax, vgi.rmax);
756
757 vgi.ymin = Math.min(vi.ymin, vgi.ymin);
758 vgi.ymax = Math.max(vi.ymax, vgi.ymax);
759 final double y0 = pv.getLtoGTransform().getTranslation().y();
760 vgi.weighted_y += y0 * wgt;
761 vgi.xmin = Math.min(vi.xmin, vgi.xmin);
762 vgi.xmax = Math.max(vi.xmax, vgi.xmax);
763 }
764
765
766 if (totwgt > 0.) {
767 vgi.weighted_r /= totwgt;
768 vgi.weighted_z /= totwgt;
769 vgi.X0 = vgi.vtot / totwgt;
770
771 vgi.weighted_y /= totwgt;
772 }
773
774 return vgi;
775 }
776
777
778
779
780
781
782 public void setDebug(final boolean debug) {
783 this.DEBUG = debug;
784 }
785
786 public void setDefaultXPlaneUsage(final boolean useDefault) {
787 _useDefaultXPlanes = useDefault;
788 }
789
790 public void setTransform(final ITransform3D transform) {
791 _detToTrk = transform;
792 }
793
794
795
796
797
798
799 private void setupTrackingVolume(final Detector det) {
800
801 final ISolid trkvol = det.getTrackingVolume().getLogicalVolume().getSolid();
802 if (trkvol instanceof Tube) {
803 final Tube trktube = (Tube) trkvol;
804 _rmax = trktube.getOuterRadius();
805 _zmax = trktube.getZHalfLength();
806 if (DEBUG) {
807 System.out.println("Ecal radius = " + _rmax);
808 System.out.println("ECal inner Z = " + _zmax);
809 }
810 }
811 }
812 }