1 package org.lcsim.event.base;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.List;
6 import java.util.Set;
7
8 import org.lcsim.event.CalorimeterHit;
9 import org.lcsim.event.Cluster;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 public class BaseCluster implements Cluster {
35
36 protected ClusterPropertyCalculator calc = new TensorClusterPropertyCalculator();
37 protected List<Cluster> clusters = new ArrayList<Cluster>();
38 protected double[] directionError = new double[6];
39
40 protected double energy;
41 protected double energyError;
42
43 protected List<Double> hitContributions = new ArrayList<Double>();
44 protected List<CalorimeterHit> hits = new ArrayList<CalorimeterHit>();
45
46 protected double iphi;
47 protected double itheta;
48
49 protected boolean needsPropertyCalculation = true;
50 protected int pid;
51
52 protected double[] position = new double[3];
53
54 protected double[] positionError = new double[6];
55 protected double[] shapeParameters;
56
57 protected double[] subdetectorEnergies = new double[0];
58 protected int type;
59
60
61
62
63 public BaseCluster() {
64 }
65
66
67
68
69
70
71
72
73 public BaseCluster(final Cluster cluster) {
74
75
76 if (cluster.getCalorimeterHits() != null) {
77 for (final CalorimeterHit hit : cluster.getCalorimeterHits()) {
78 this.hits.add(hit);
79 }
80 }
81
82
83 if (cluster.getHitContributions() != null) {
84 this.hitContributions = new ArrayList<Double>();
85 for (final Double contribution : cluster.getHitContributions()) {
86 this.hitContributions.add(contribution);
87 }
88 }
89
90
91 this.energy = cluster.getEnergy();
92 this.energyError = cluster.getEnergyError();
93
94
95 if (cluster.getPosition() != null) {
96 this.position = new double[cluster.getPosition().length];
97 System.arraycopy(cluster.getPosition(), 0, this.position, 0, cluster.getPosition().length);
98 }
99
100
101 if (cluster.getPositionError() != null) {
102 this.positionError = new double[cluster.getPositionError().length];
103 System.arraycopy(cluster.getPositionError(), 0, this.positionError, 0, cluster.getPositionError().length);
104 }
105
106
107 this.iphi = cluster.getIPhi();
108 this.itheta = cluster.getITheta();
109
110
111 if (cluster.getDirectionError() != null) {
112 this.directionError = new double[cluster.getDirectionError().length];
113 System.arraycopy(cluster.getDirectionError(), 0, this.directionError, 0, cluster.getDirectionError().length);
114 }
115
116
117 if (cluster.getShape() != null) {
118 this.shapeParameters = new double[cluster.getShape().length];
119 System.arraycopy(cluster.getShape(), 0, this.shapeParameters, 0, cluster.getShape().length);
120 }
121
122
123 this.type = cluster.getType();
124 this.pid = cluster.getParticleId();
125 }
126
127
128
129
130
131
132 public BaseCluster(final List<CalorimeterHit> hits) {
133 this.addHits(hits);
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 public BaseCluster(final List<CalorimeterHit> hits, final double energy, final double energyError, final double[] position,
152 final double[] positionError, final double iphi, final double itheta, final double[] directionError, final double[] shapeParameters,
153 final int type, final int pid) {
154
155 this.addHits(hits);
156
157
158 this.energy = energy;
159 this.energyError = energyError;
160
161 this.position = position;
162 this.positionError = positionError;
163
164 this.iphi = iphi;
165 this.itheta = itheta;
166
167 this.directionError = directionError;
168 this.shapeParameters = shapeParameters;
169
170 this.type = type;
171 this.pid = pid;
172
173 this.needsPropertyCalculation = false;
174 }
175
176
177
178
179
180
181 public void addCluster(final Cluster cluster) {
182 clusters.add(cluster);
183 final List<CalorimeterHit> clusterHits = cluster.getCalorimeterHits();
184 for (int i = 0; i < clusterHits.size(); i++) {
185 hits.add(clusterHits.get(i));
186 hitContributions.add(clusterHits.get(i).getCorrectedEnergy());
187 }
188 energy += cluster.getEnergy();
189 needsPropertyCalculation = true;
190 }
191
192
193
194
195
196
197
198
199
200
201 public void addClusters(final List<Cluster> clusters) {
202 for (final Cluster cluster : clusters) {
203 this.addCluster(cluster);
204 }
205 }
206
207
208
209
210
211
212 public void addHit(final CalorimeterHit hit) {
213 this.addHit(hit, hit.getCorrectedEnergy());
214 needsPropertyCalculation = true;
215 }
216
217
218
219
220
221
222
223 public void addHit(final CalorimeterHit hit, final double contribution) {
224 hits.add(hit);
225 hitContributions.add(contribution);
226 energy += contribution;
227 needsPropertyCalculation = true;
228 }
229
230
231
232
233
234
235 public void addHits(final List<CalorimeterHit> hits) {
236 for (final CalorimeterHit hit : hits) {
237 this.addHit(hit);
238 }
239 }
240
241
242
243
244
245
246
247 public void calculateProperties() {
248 if (!this.hasPropertyCalculator()) {
249 throw new RuntimeException("No ClusterPropertyCalculator is set on this object.");
250 }
251 calc.calculateProperties(this);
252 this.setPosition(calc.getPosition());
253 this.setPositionError(calc.getPositionError());
254 this.setIPhi(calc.getIPhi());
255 this.setITheta(calc.getITheta());
256 this.setDirectionError(calc.getDirectionError());
257 this.setShapeParameters(calc.getShapeParameters());
258 this.setNeedsPropertyCalculation(false);
259 }
260
261
262
263
264 void checkCalculateProperties() {
265 if (this.needsPropertyCalculation()) {
266 this.calculateProperties();
267 }
268 }
269
270
271
272
273
274
275 @Override
276 public Object clone() {
277 return new BaseCluster(this);
278 }
279
280
281
282
283
284
285 @Override
286 public List<CalorimeterHit> getCalorimeterHits() {
287 return hits;
288 }
289
290
291
292
293
294
295 @Override
296 public List<Cluster> getClusters() {
297 return clusters;
298 }
299
300
301
302
303
304
305 @Override
306 public double[] getDirectionError() {
307 this.checkCalculateProperties();
308 return directionError;
309 }
310
311
312
313
314
315
316 @Override
317 public double getEnergy() {
318 return energy;
319 }
320
321
322
323
324
325
326 @Override
327 public double getEnergyError() {
328 return energyError;
329 }
330
331
332
333
334
335
336
337
338 @Override
339 public double[] getHitContributions() {
340 final double[] arrayCopy = new double[hitContributions.size()];
341 for (int i = 0; i < hitContributions.size(); i++) {
342 arrayCopy[i] = hitContributions.get(i);
343 }
344 return arrayCopy;
345 }
346
347
348
349
350
351
352 @Override
353 public double getIPhi() {
354 this.checkCalculateProperties();
355 return iphi;
356 }
357
358
359
360
361
362
363 @Override
364 public double getITheta() {
365 this.checkCalculateProperties();
366 return itheta;
367 }
368
369
370
371
372
373
374
375
376
377
378 @Override
379 public int getParticleId() {
380 return pid;
381 }
382
383
384
385
386
387
388 @Override
389 public double[] getPosition() {
390 this.checkCalculateProperties();
391 return position;
392 }
393
394
395
396
397
398
399 @Override
400 public double[] getPositionError() {
401 this.checkCalculateProperties();
402 return positionError;
403 }
404
405
406
407
408
409
410 @Override
411 public double[] getShape() {
412 this.checkCalculateProperties();
413 return shapeParameters;
414 }
415
416
417
418
419
420
421 @Override
422 public int getSize() {
423 final Set<CalorimeterHit> hitSet = new HashSet<CalorimeterHit>(this.hits);
424 for (final Cluster cluster : clusters) {
425 hitSet.addAll(cluster.getCalorimeterHits());
426 }
427 final int size = hitSet.size();
428 hitSet.clear();
429 return size;
430 }
431
432
433
434
435
436
437 @Override
438 public double[] getSubdetectorEnergies() {
439 return subdetectorEnergies;
440 }
441
442
443
444
445
446
447 @Override
448 public int getType() {
449 return type;
450 }
451
452
453
454
455
456
457 public boolean hasPropertyCalculator() {
458 return calc != null;
459 }
460
461
462
463
464
465
466 public boolean needsPropertyCalculation() {
467 return needsPropertyCalculation;
468 }
469
470
471
472
473
474
475 public void removeHit(final CalorimeterHit hit) {
476 final int index = hits.indexOf(hit);
477 hits.remove(hit);
478 final double hitEnergy = hit.getCorrectedEnergy();
479 energy -= hitEnergy;
480 hitContributions.remove(index);
481 needsPropertyCalculation = true;
482 }
483
484
485
486
487
488
489
490 public void setDirectionError(final double[] directionError) {
491 if (directionError.length != 6) {
492 throw new IllegalArgumentException("The directionError array argument has the wrong length: " + position.length);
493 }
494 this.directionError = directionError;
495 }
496
497
498
499
500
501
502
503
504
505
506 public void setEnergy(final double energy) {
507 this.energy = energy;
508 }
509
510
511
512
513
514
515 public void setEnergyError(final double energyError) {
516 this.energyError = energyError;
517 }
518
519
520
521
522
523
524 public void setIPhi(final double iphi) {
525 this.iphi = iphi;
526 }
527
528
529
530
531
532
533 public void setITheta(final double itheta) {
534 this.itheta = itheta;
535 }
536
537
538
539
540
541
542 public void setNeedsPropertyCalculation(final boolean needsPropertyCalculation) {
543 this.needsPropertyCalculation = needsPropertyCalculation;
544 }
545
546
547
548
549
550
551 public void setParticleId(final int pid) {
552 this.pid = pid;
553 }
554
555
556
557
558
559
560
561
562
563
564
565 public void setPosition(final double[] position) {
566 if (position.length != 3) {
567 throw new IllegalArgumentException("The position array argument has the wrong length: " + position.length);
568 }
569 this.position = position;
570 }
571
572
573
574
575
576
577
578 public void setPositionError(final double[] positionError) {
579 if (positionError.length != 6) {
580 throw new IllegalArgumentException("The positionError array argument has the wrong length: " + position.length);
581 }
582 this.positionError = positionError;
583 }
584
585
586
587
588
589
590 public void setPropertyCalculator(final ClusterPropertyCalculator calc) {
591 this.calc = calc;
592 }
593
594
595
596
597
598
599 public void setShapeParameters(final double[] shapeParameters) {
600 this.shapeParameters = shapeParameters;
601 }
602
603
604
605
606
607
608 public void setSubdetectorEnergies(final double[] subdetectorEnergies) {
609 this.subdetectorEnergies = subdetectorEnergies;
610 }
611
612
613
614
615
616
617 public void setType(final int type) {
618 this.type = type;
619 }
620 }