Belle II Software  release-08-01-10
ecl_packer_unpacker.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 # Inspired by cdc/tests/cdc_packer_unpacker.py
13 
14 # This test checks if ECLDigits that are packed and then unpacked are identical to the originals.
15 # ECLDigits are obtained in 2 ways:
16 # 1) From simulated muons
17 # 2) "Custom" ECLDigits that have different combinations of parameters spanning the allowed range.
18 
19 import basf2 as b2
20 from ROOT import Belle2
21 from unittest import TestCase
22 from ROOT import gRandom
23 import simulation
24 import itertools
25 
26 logLevel = b2.LogLevel.INFO # LogLevel.DEBUG #
27 b2.set_random_seed(42)
28 
29 eclDigitsDatastoreName = 'ECLDigits'
30 unpackerOutputDatastoreName = 'someECLUnpackerDatastoreName'
31 
32 
33 class addECLDigitsModule(b2.Module):
34  """
35  Adds ECLDigits with very large/small time/amplitude values
36  """
37 
38  def __init__(self):
39  """constructor"""
40  super().__init__()
41  amps = [0, 1, 100000, 262015]
42  times = [-2048, -100, 0, 100, 2047]
43  qualitys = [0, 1, 2, 3]
44  chis = [0, 1, 254, 511]
45  paramNames = ["amp", "time", "quality", "chi"]
46 
47  self.digitParamsdigitParams = [dict(zip(paramNames, params)) for params in itertools.product(amps, times, qualitys, chis)]
48 
49  def event(self):
50  """
51  event function
52  """
53  eclDigitsFromSimulation = Belle2.PyStoreArray(eclDigitsDatastoreName)
54 
55  # Check for used cellIds
56  usedCellIds = list(map(lambda eclDigit: eclDigit.getCellId(), eclDigitsFromSimulation))
57 
58  # Create new ECLDigits and add them to datastore
59  for digitParam in self.digitParamsdigitParams:
60  # Skip combination of quality != 2 and chi != 0. Electronics can't output this
61  if (digitParam['quality'] != 2) and (digitParam['chi'] != 0):
62  continue
63 
64  # Skip combination of quality == 2 and amp != 0. Electronics can't output this
65  if (digitParam['quality'] == 2) and (digitParam['time'] != 0):
66  continue
67 
68  # Choose cellId that's not already used
69  cellId = int(gRandom.Uniform(1, 8736))
70  while cellId in usedCellIds:
71  cellId = int(gRandom.Uniform(1, 8736))
72 
73  usedCellIds.append(cellId)
74  # Create new ECLDigit
75  eclDigit = Belle2.ECLDigit()
76 
77  # Fill ECLDigit
78  eclDigit.setCellId(cellId)
79  eclDigit.setAmp(digitParam['amp'])
80  eclDigit.setTimeFit(digitParam['time'])
81  eclDigit.setQuality(digitParam['quality'])
82  eclDigit.setChi(digitParam['chi'])
83 
84  # Add ECLDigit to datastore
85  newDigit = eclDigitsFromSimulation.appendNew()
86  newDigit.__assign__(eclDigit)
87 
88 
89 class ECLPackerUnpackerTestModule(b2.Module):
90  """
91  module which checks if two collections of ECLDigits are equal
92  """
93 
94  def sortECLDigits(self, unsortedPyStoreArray):
95  """ use a some information to sort the ECLDigits list
96  Returns a python-list containing the ECLDigits
97  """
98  # first convert to a python-list to be able to sort
99  py_list = [x for x in unsortedPyStoreArray]
100 
101  # sort via a hierachy of sort keys
102  return sorted(
103  py_list,
104  key=lambda x: (
105  x.getCellId()))
106 
107  def event(self):
108  """
109  event function
110  """
111 
112  # load the ECLDigits that were packed and unpacked
113  eclDigitsPackedUnpacked_unsorted = Belle2.PyStoreArray(unpackerOutputDatastoreName)
114  # ECLDigits direct from simulation
115  eclDigitsFromSimulation_unsorted = Belle2.PyStoreArray(eclDigitsDatastoreName)
116 
117  if not len(eclDigitsFromSimulation_unsorted) == len(eclDigitsPackedUnpacked_unsorted):
118  b2.B2FATAL("Different number of ECLDigits from simulation and after packing+unpacking")
119 
120  eclDigitsPackedUnpacked = self.sortECLDigitssortECLDigits(eclDigitsPackedUnpacked_unsorted)
121  eclDigitsFromSimulation = self.sortECLDigitssortECLDigits(eclDigitsFromSimulation_unsorted)
122 
123  tc = TestCase('__init__')
124 
125  # check all quantities between the direct and the packed/unpacked ECLDigits
126  for idx in range(len(eclDigitsPackedUnpacked)):
127  digit = eclDigitsFromSimulation[idx]
128  digitPackedUnpacked = eclDigitsPackedUnpacked[idx]
129 
130  b2.B2DEBUG(5, 'MC digit: cellid = ' +
131  str(digit.getCellId()) +
132  ', amp = ' +
133  str(digit.getAmp()) +
134  ', time = ' +
135  str(digit.getTimeFit()) +
136  ', quality = ' +
137  str(digit.getQuality()) +
138  ', chi = ' +
139  str(digit.getChi()) +
140  '\nUnpackedDigit: cellid = ' +
141  str(digitPackedUnpacked.getCellId()) +
142  ', amp = ' +
143  str(digitPackedUnpacked.getAmp()) +
144  ', time = ' +
145  str(digitPackedUnpacked.getTimeFit()) +
146  ', quality = ' +
147  str(digitPackedUnpacked.getQuality()) +
148  ', chi = ' +
149  str(digitPackedUnpacked.getChi()))
150 
151  tc.assertEqual(digit.getCellId(), digitPackedUnpacked.getCellId())
152  tc.assertEqual(digit.getAmp(), digitPackedUnpacked.getAmp())
153  tc.assertEqual(digit.getTimeFit(), digitPackedUnpacked.getTimeFit())
154  tc.assertEqual(digit.getQuality(), digitPackedUnpacked.getQuality())
155  tc.assertEqual(digit.getChi(), digitPackedUnpacked.getChi())
156 
157 
158 main = b2.create_path()
159 # Create Event information
160 eventinfosetter = b2.register_module('EventInfoSetter')
161 eventinfosetter.param({'evtNumList': [10]})
162 main.add_module(eventinfosetter)
163 
164 # to run the framework the used modules need to be registered
165 particlegun = b2.register_module('ParticleGun')
166 particlegun.param('pdgCodes', [13, -13])
167 particlegun.param('nTracks', 10)
168 main.add_module(particlegun)
169 
170 # add simulation for ECL only
171 simulation.add_simulation(main, components=['ECL'])
172 b2.set_module_parameters(main, type="Geometry", useDB=False, components=["ECL"])
173 
174 # Add ECLDigits with wide range of amp, time, quality, chi2
175 main.add_module(addECLDigitsModule())
176 
177 # add the packer which packs the ECLDigits from the simulation
178 ecl_packer = b2.register_module('ECLPacker')
179 main.add_module(ecl_packer)
180 
181 # add the unpacker which unpacks the RawECL into ECLDigits and store them in a seperate datstore container
182 ecl_unpacker = b2.register_module('ECLUnpacker')
183 # set the unpacker output datastore name, so that we don't overwrite the "normal" ECLDigits
184 ecl_unpacker.param('ECLDigitsName', unpackerOutputDatastoreName)
185 main.add_module(ecl_unpacker)
186 
187 # Run test module to check if the original ECLDigits and the ones that were packed and unpacked are identical
188 eclPackUnpackerChecker = ECLPackerUnpackerTestModule()
189 main.add_module(eclPackUnpackerChecker, logLevel=logLevel)
190 
191 
192 # Process events
193 b2.process(main)
Class to store ECL digitized hits (output of ECLDigi) relation to ECLHit filled in ecl/modules/eclDig...
Definition: ECLDigit.h:24
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
def add_simulation(path, components=None, bkgfiles=None, bkgOverlay=True, forceSetPXDDataReduction=False, usePXDDataReduction=True, cleanupPXDDataReduction=True, generate_2nd_cdc_hits=False, simulateT0jitter=True, isCosmics=False, FilterEvents=False, usePXDGatedMode=False, skipExperimentCheckForBG=False, save_slow_pions_in_mc=False)
Definition: simulation.py:121