1 package org.lcsim.detector;
2
3 import hep.physics.vec.Hep3Vector;
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.lcsim.detector.identifier.IExpandedIdentifier;
9 import org.lcsim.detector.identifier.IIdentifier;
10 import org.lcsim.detector.identifier.IIdentifierHelper;
11 import org.lcsim.detector.identifier.Identifier;
12 import org.lcsim.detector.solids.Inside;
13
14
15
16
17
18
19
20 public class DetectorElement implements IDetectorElement
21 {
22 private IDetectorElementContainer children;
23 private IGeometryInfo geometry;
24 private IDetectorElement parent;
25 private IIdentifier id;
26 private IIdentifierHelper helper;
27 private IParameters parameters;
28 private IReadout readout;
29 private String name;
30
31
32
33
34 protected DetectorElement()
35 {
36 }
37
38
39
40
41
42
43
44
45
46
47
48 public DetectorElement(String name, IDetectorElement parent, IPhysicalVolumePath support, IIdentifier id)
49 {
50 setup(name, parent, support, id);
51 register();
52 }
53
54
55
56
57
58
59
60
61 public DetectorElement(String name, IDetectorElement parent, IPhysicalVolumePath support)
62 {
63 setup(name, parent, support, null);
64 register();
65 }
66
67
68
69
70
71
72
73
74
75 public DetectorElement(String name, IDetectorElement parent, String support)
76 {
77 setup(name, parent, support, id);
78 register();
79 }
80
81
82
83
84
85
86
87
88
89 public DetectorElement(String name, IDetectorElement parent, String support, IIdentifier id)
90 {
91 setup(name, parent, support, id);
92 register();
93 }
94
95
96
97
98
99
100
101
102 public DetectorElement(String name, IDetectorElement parent)
103 {
104 setup(name, parent, (IPhysicalVolumePath) null, null);
105 register();
106 }
107
108
109
110
111 public DetectorElement(String name, IDetectorElement parent, IIdentifier id)
112 {
113 setup(name, parent, (IPhysicalVolumePath) null, id);
114 register();
115 }
116
117
118
119
120
121
122
123 public DetectorElement(String name)
124 {
125 this.name = name;
126 register();
127 }
128
129 public String getName()
130 {
131 return name;
132 }
133
134
135
136
137
138
139
140
141
142 public void setParent(IDetectorElement parent)
143 {
144 if (this.parent != null)
145 {
146 throw new RuntimeException("The IDetectorElement <" + getName() + "> already has a parent!");
147 }
148
149 if (parent == null)
150 {
151 throw new IllegalArgumentException("The parent IDetectorElement is null!");
152 }
153
154 this.parent = parent;
155 ((DetectorElement) parent).addChild(this);
156 }
157
158
159
160
161 private void register()
162 {
163 if (!DetectorElementStore.getInstance().contains(this))
164 {
165 DetectorElementStore.getInstance().add(this);
166 }
167 }
168
169 private void checkName(String name)
170 {
171 if (name == null)
172 throw new IllegalArgumentException("Name argument is null!");
173
174 if (name.length() == 0)
175 throw new IllegalArgumentException("Name is zero length!");
176
177 if (name.trim().length() == 0)
178 throw new IllegalArgumentException("Name contains only white space!");
179
180 if (name.contains("/"))
181 throw new IllegalArgumentException("Name contains a '/', which is not a legal character!");
182 }
183
184 private void setup(String name, IDetectorElement parent, IPhysicalVolumePath support, IIdentifier id)
185 {
186 this.name = name;
187
188 checkName(this.name);
189
190 if (parent != null)
191 {
192 setParent(parent);
193 }
194
195 if (support != null)
196 {
197 setSupport(support);
198 }
199
200 if (id != null)
201 {
202 setIdentifier(id);
203 }
204 }
205
206 private void setup(String name, IDetectorElement parent, String support, IIdentifier id)
207 {
208 this.name = name;
209
210 checkName(this.name);
211
212 if (parent != null)
213 {
214 setParent(parent);
215 }
216
217 if (support != null)
218 {
219 setSupport(support);
220 }
221
222 if (id != null)
223 {
224 setIdentifier(id);
225 }
226 }
227
228 public void setSupport(IPhysicalVolumePath support)
229 {
230 createGeometryInfo(support);
231 }
232
233 public void setSupport(String path)
234 {
235 createGeometryInfo(path);
236 }
237
238 private void createGeometryInfo(IPhysicalVolumePath path)
239 {
240 geometry = new GeometryInfo(this, path);
241 }
242
243 private void createGeometryInfo(String path)
244 {
245 IPhysicalVolumeNavigator nav = PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator();
246 geometry = new GeometryInfo(this, nav.getPath(path));
247 }
248
249 protected void addChild(IDetectorElement child)
250 {
251 if (children == null)
252 {
253 children = new DetectorElementContainer();
254 }
255 children.add(child);
256 }
257
258 public IDetectorElementContainer getChildren()
259 {
260 if (children == null)
261 {
262 children = new DetectorElementContainer();
263 }
264 return children;
265 }
266
267 public boolean hasChildren()
268 {
269 if (children == null)
270 {
271 return false;
272 }
273 return children.size() != 0;
274 }
275
276 public IGeometryInfo getGeometry()
277 {
278 return geometry;
279 }
280
281 public IDetectorElement getParent()
282 {
283 return parent;
284 }
285
286 public IExpandedIdentifier getExpandedIdentifier()
287 {
288 try
289 {
290 return getIdentifierHelper().unpack(id);
291 }
292 catch (Exception x)
293 {
294 throw new RuntimeException(x);
295 }
296 }
297
298 public IIdentifier getIdentifier()
299 {
300
301 if (id == null)
302 {
303 id = new Identifier();
304 }
305 return id;
306 }
307
308 public void setIdentifier(IIdentifier id)
309 {
310 this.id = id;
311 }
312
313 public boolean hasGeometryInfo()
314 {
315 return geometry != null;
316 }
317
318 public IDetectorElement findDetectorElement(Hep3Vector globalPoint)
319 {
320 IDetectorElement srch = null;
321
322 if (hasGeometryInfo())
323 {
324 Inside inside = getGeometry().inside(globalPoint);
325 if (inside == Inside.INSIDE)
326 {
327 srch = this;
328 }
329 }
330
331
332 if (hasChildren())
333 {
334 for (IDetectorElement child : getChildren())
335 {
336 IDetectorElement childSrch = child.findDetectorElement(globalPoint);
337 if (childSrch != null)
338 {
339 srch = childSrch;
340 }
341 }
342 }
343
344 return srch;
345 }
346
347 public IReadout getReadout()
348 {
349 if (readout == null)
350 {
351 readout = createReadout();
352 }
353 return readout;
354 }
355
356 public void setReadout(IReadout readout)
357 {
358 this.readout = readout;
359 }
360
361 public IReadout createReadout()
362 {
363 return new Readout();
364 }
365
366 public boolean hasReadout()
367 {
368 return this.readout != null;
369 }
370
371 public IParameters getParameters()
372 {
373 return parameters;
374 }
375
376 public IDetectorElementContainer getAncestry()
377 {
378 IDetectorElementContainer parents = new DetectorElementContainer();
379
380 parents.add(this);
381
382 IDetectorElement par = this.getParent();
383
384 while (par != null)
385 {
386 parents.add(par);
387 par = par.getParent();
388 }
389
390 java.util.Collections.reverse(parents);
391
392 return parents;
393 }
394
395 public void clearReadouts()
396 {
397 if (hasReadout())
398 {
399 readout.clear();
400 }
401
402 if (hasChildren())
403 {
404 for (IDetectorElement child : getChildren())
405 {
406 child.clearReadouts();
407 }
408 }
409 }
410
411 public boolean isDescendant(IDetectorElement de)
412 {
413 boolean isDesc = false;
414 if (hasChildren())
415 {
416 if (children.contains(de))
417 {
418 return isDesc = true;
419 }
420 else
421 {
422 for (IDetectorElement child : children)
423 {
424 isDesc = child.isDescendant(de);
425 if (isDesc)
426 break;
427 }
428 }
429 }
430 return isDesc;
431 }
432
433
434
435
436
437
438
439 public void setIdentifierHelper(IIdentifierHelper helper)
440 {
441 this.helper = helper;
442 }
443
444 public IIdentifierHelper getIdentifierHelper()
445 {
446 if (helper == null)
447 {
448 IDetectorElement search = getParent();
449 while (search != null)
450 {
451 if (search.getIdentifierHelper() != null)
452 return search.getIdentifierHelper();
453 search = search.getParent();
454 }
455 }
456
457
458 return helper;
459 }
460
461 public void traverseDescendantsPreOrder(IDetectorElementVisitor visitor)
462 {
463 traversePreOrder(this, visitor);
464 }
465
466 public void traverseDescendantsPostOrder(IDetectorElementVisitor visitor)
467 {
468 traversePostOrder(this, visitor);
469 }
470
471 private static final void traversePreOrder(IDetectorElement detectorElement, IDetectorElementVisitor visitor)
472 {
473
474 if (visitor.isDone())
475 {
476 return;
477 }
478
479
480 visitor.visit(detectorElement);
481
482
483 if (detectorElement.hasChildren())
484 {
485 for (IDetectorElement child : detectorElement.getChildren())
486 {
487 traversePreOrder(child, visitor);
488 }
489 }
490 }
491
492 private static final void traversePostOrder(IDetectorElement detectorElement, IDetectorElementVisitor visitor)
493 {
494
495 if (visitor.isDone())
496 {
497 return;
498 }
499
500
501 if (detectorElement.hasChildren())
502 {
503 for (IDetectorElement child : detectorElement.getChildren())
504 {
505 traversePreOrder(child, visitor);
506 }
507 }
508
509
510 visitor.visit(detectorElement);
511 }
512
513 public void traverseAncestors(IDetectorElementVisitor visitor)
514 {
515 IDetectorElement detelem = this;
516 while (detelem != null)
517 {
518 visitor.visit(detelem);
519 detelem = detelem.getParent();
520 }
521 }
522
523 private class TypeSearch<T extends IDetectorElement> implements IDetectorElementVisitor
524 {
525 Class<T> klass;
526 List<T> results = new ArrayList<T>();
527
528 TypeSearch(Class<T> klass)
529 {
530 this.klass = klass;
531 }
532
533 public void visit(IDetectorElement detectorElement)
534 {
535 if (klass.isInstance(detectorElement))
536 {
537 results.add(klass.cast(detectorElement));
538 }
539 }
540
541 public List<T> getResult()
542 {
543 return results;
544 }
545
546 public boolean isDone()
547 {
548 return false;
549 }
550 }
551
552 public <T extends IDetectorElement> List<T> findAncestors(Class<T> klass)
553 {
554 TypeSearch<T> search = new TypeSearch<T>(klass);
555 traverseAncestors(search);
556 return search.getResult();
557 }
558
559 public <T extends IDetectorElement> List<T> findDescendants(Class<T> klass)
560 {
561 TypeSearch<T> search = new TypeSearch<T>(klass);
562 traverseDescendantsPreOrder(search);
563 return search.getResult();
564 }
565
566 public boolean isAncestor(IDetectorElement de)
567 {
568 return getAncestry().contains(de);
569 }
570
571 public void setParameters(IParameters parameters)
572 {
573 if (parameters == null)
574 {
575 throw new IllegalArgumentException("The parameters object is null.");
576 }
577 this.parameters = parameters;
578 }
579
580
581
582
583
584
585 public IDetectorElementContainer findDetectorElement(IIdentifier id)
586 {
587 return DetectorElementStore.getInstance().find(id);
588 }
589
590 public IDetectorElement findDetectorElement(String pathString)
591 {
592 return findDetectorElement(pathString.split("/"));
593 }
594
595 public IDetectorElement findDetectorElement(String[] path)
596 {
597 IDetectorElement de = this;
598 for (int i = 0; i < path.length; i++)
599 {
600
601
602 if (!de.hasChildren() && i != path.length)
603 throw new RuntimeException("Not enough child DetectorElements for path argument.");
604
605 IDetectorElementContainer children = de.getChildren();
606
607 IDetectorElementContainer matches = children.find(path[i]);
608 if (matches.size() > 1)
609 throw new RuntimeException("Found more than one match for path component <" + path[i] + ">.");
610
611
612
613 if (matches.size() == 0)
614 {
615 throw new RuntimeException("A DetectorElement for the path component <" + path[i] + "> was not found.");
616 }
617
618 de = matches.get(0);
619 }
620 return de;
621 }
622
623 public IDetectorElement getTop()
624 {
625 IDetectorElement top;
626 if (this.getParent() == null)
627 return this;
628 else
629 top = this.getParent();
630
631 while (true)
632 {
633 if (top.getParent() == null)
634 break;
635 top = top.getParent();
636 }
637 return top;
638 }
639
640 public boolean isSensitive()
641 {
642 if (!hasGeometryInfo())
643 return false;
644 IPhysicalVolume pv = getGeometry().getPhysicalVolume();
645 if (pv != null)
646 return pv.isSensitive();
647 else
648 return false;
649 }
650
651 public void initialize() {
652 }
653 }