Belle II Software development
checkRandomNumbers.py
1#!/usr/bin/env python3
2
3
10
11# this is a test executable, not a module so we don't need doxygen warnings
12# @cond SUPPRESS_DOXYGEN
13
14"""
15Check that random numbers don't change and are consistent.
16
17This steering file runs through a set of exp/run combinations and prints
18the first few random numbers in initialize(), beginRun(), event() and endRun().
19
20It also sets the framework to debugging output and shows the information used
21to calculate the random generator state.
22"""
23
24import struct
25import basf2
26from ROOT import gRandom
27
28
29def double_to_hex(double):
30 """Convert a double to a hex string representation"""
31 # we pack the float to a little-endian double end interpret it as
32 # little-endian unsigned 64 bit int
33 return f"{struct.unpack('<Q', struct.pack('<d', double))[0]:016X}"
34
35
36class RandomTestModule(basf2.Module):
37 """Print some random numbers to check reproducibility"""
38
39 def __init__(self, name):
40 """Make sure we can run in multiple processes"""
41 super().__init__()
42 self.set_property_flags(basf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED)
43
44 self.name = name
45
46 def get_numbers(self, name):
47 """Print the first 20 random numbers"""
48 numbers = [f"First 20 random values in {self.name}::{name}()"]
49 for row in range(5):
50 numbers.append(", ".join(double_to_hex(gRandom.Rndm()) for i in range(4)))
51 basf2.B2INFO("\n ".join(numbers))
52
53 def initialize(self):
54 """Show random numbers in initialize"""
55 self.get_numbers("initialize")
56
57 def beginRun(self):
58 """Show random numbers in beginRun"""
59 self.get_numbers("beginRun")
60
61 def event(self):
62 """Show random numbers in event"""
63 self.get_numbers("event")
64
65 def endRun(self):
66 """Show random numbers in endRun"""
67 self.get_numbers("endRun")
68
69
70
71main = basf2.Path()
72# generate a few runs which look good in hex
73main.add_module("EventInfoSetter", evtNumList=[3, 4, 5],
74 runList=[0x11121314, 0x21222324, 0x31323334],
75 expList=[0x123, 0x234, 0x345])
76# We could add a single processing RandomBarrier to check random barrier
77# transport in multi processing. But since output is unordered in multi
78# processing we don't do this in the automatic test
79# main.add_module("RandomBarrier").set_property_flags(0)
80main.add_module("EventInfoPrinter")
81main.add_module(RandomTestModule("test1"))
82main.add_module("RandomBarrier")
83main.add_module(RandomTestModule("test2"))
84
85
86logging_framework = basf2.logging.package("framework")
87# now the libraries are loaded so we can set the loglevel to debug, set the seed
88# and start processing
89logging_framework.set_log_level(basf2.LogLevel.DEBUG)
90logging_framework.set_debug_level(200)
91logging_framework.set_info(basf2.LogLevel.DEBUG, basf2.LogInfo.LEVEL | basf2.LogInfo.MESSAGE)
92basf2.set_random_seed("this is the seed")
93
94basf2.process(main)
95
96# @endcond