00001
00002
00003 from DybPython.DybPythonAlg import DybPythonAlg, SUCCESS, FAILURE
00004 from GaudiPython import gbl
00005 from ROOT import gRandom
00006
00007 class RootRandom(object):
00008 def __init__(self,maximum):
00009 self.max = maximum
00010 self.name = 'ROOT'
00011
00012 def __call__(self):
00013 num = gRandom.Uniform(self.max)
00014 assert 0<=num<self.max, 'Got bogus ROOT random: %f'%num
00015 return num
00016
00017 class ClhepRandom(object):
00018 def __init__(self, maximum, rndmsvc):
00019 self.max = maximum
00020 self.name = 'CLHEP'
00021 flat = gbl.Rndm.Flat(0,maximum)
00022 self.flat = gbl.Rndm.Numbers(rndmsvc,flat)
00023
00024 def __call__(self):
00025 num = self.flat()
00026 assert 0<=num<self.max, 'Got bogus CLHEP random: %f'%num
00027 return num
00028
00029 class RandomEater(object):
00030 def __init__(self,nrans,ran):
00031 self.ran = ran
00032 self.nrans = nrans
00033 self.count = 0
00034 self.numbers = [0]*nrans
00035 self.avg = [0]*nrans
00036 self.rms = [0]*nrans
00037 self.nevents = 0
00038
00039 def clear(self):
00040 if self.nrans != self.count:
00041 raise RuntimeError, "RandomEater not called enough %d != %d" %\
00042 (self.ntrans,self.count)
00043
00044 self.avg = map(lambda x: x[0]+x[1], zip(self.avg,self.numbers))
00045 self.rms = map(lambda x: x[0]+x[1]*x[1], zip(self.rms,self.numbers))
00046 self.numbers = [0]*self.nrans
00047 self.count = 0
00048 self.nevents += 1
00049 return
00050
00051 def check(self):
00052 import math
00053 avg = map(lambda x: x/self.nevents, self.avg)
00054 rms = map(lambda x: math.sqrt((x[1] - self.nevents*x[0]**2)/(self.nevents-1)),
00055 zip(avg,self.rms))
00056
00057 nbad = 0
00058 count = 0;
00059 target_mean = self.ran.max/2.0
00060 target_width = self.ran.max/math.sqrt(12)
00061 target_mean_eps = 100*target_width/self.nevents
00062 target_width_eps = 0.1*target_width
00063
00064 for mean, width in zip(avg,rms):
00065
00066 if abs(mean-target_mean) > target_mean_eps or \
00067 abs(width-target_width) > target_width_eps:
00068 print 'Rogue %s random at %d: %f(%f,%f) +/- %f(%f,%f)' % \
00069 (self.ran.name,count,
00070 mean,mean-target_mean,(mean-target_mean)/target_mean_eps,
00071 width,width-target_width,(width-target_width)/target_width_eps)
00072 nbad += 1
00073 count += 1
00074 continue
00075 return nbad
00076
00077
00078 def __call__(self):
00079 if self.count > self.nrans:
00080 raise RuntimeError, 'RandomEater called more than max %d'%self.nrans
00081 num = self.ran()
00082 self.numbers[self.count] = num
00083 self.count += 1
00084 return num
00085 pass
00086
00087 class EatRandom(DybPythonAlg):
00088
00089 def __init__(self, name = 'EatRandom', nrans = 100):
00090 '''
00091 '''
00092 DybPythonAlg.__init__(self,name)
00093 self.clhep = None
00094 self.root = None
00095 self.maximum = 100.0
00096 self.nrans = nrans
00097 return
00098
00099 def initialize(self):
00100 sc = DybPythonAlg.initialize(self)
00101 if sc.isFailure(): return sc
00102
00103 rndmsvc = self.svc('IRndmGenSvc','RndmGenSvc')
00104 assert rndmsvc.engine(), 'Good not get random engine from random svc'
00105 self.clhep = RandomEater(self.nrans,ClhepRandom(self.maximum,rndmsvc))
00106
00107 self.root = RandomEater(self.nrans,RootRandom(self.maximum))
00108
00109 return sc
00110
00111 def execute(self):
00112 for n in range(self.nrans):
00113 self.clhep()
00114 self.root()
00115 continue
00116
00117 self.clhep.clear()
00118 self.root.clear()
00119
00120 return SUCCESS
00121
00122 def finalize(self):
00123 assert 0 == self.root.check(),'ERROR, got bad ROOT randoms'
00124 assert 0 == self.clhep.check(),'ERROR, Got bad CLHEP randoms'
00125
00126 return SUCCESS
00127
00128
00129 def configure(argv=None):
00130
00131 from DybAlg.DybAlgConf import DybShuffle
00132 rs = DybShuffle("random_seeder")
00133 try:
00134 burn = argv[0]
00135 except IndexError:
00136 print 'Using default burn count',rs.BurnCount
00137 else:
00138 rs.BurnCount = int(burn)
00139 print 'Setting burn to',rs.BurnCount
00140
00141
00142
00143
00144
00145
00146
00147 return
00148
00149 def run(app):
00150 alg = EatRandom()
00151 app.addAlgorithm(alg)
00152 return
00153
00154