5 Decay File Parser to check whether a decay file is correctly defined before committing to svn
16 mesg(
'Starting the decfile check')
17 query(
'Opening decfile')
19 fail([
'Please pass the decfile as the first argument.'])
22 filename = sys.argv[1]
23 dkfilespath = os.path.dirname(os.path.abspath(sys.argv[0])) +
'/' \
24 + settings.dkfilespath
26 if not os.path.exists(filename):
27 fail([
'The file does not exist'])
29 elif not os.path.isfile(filename):
31 fail([
'The path does not point to a regular file.'])
36 fail([
'Unknown error opening file.'])
41 documentation_inprocess =
False
60 decay_inprocess =
False
73 def getfield(line, string):
75 if string +
':' in line:
76 query(
'Now parsing: ' + string)
77 tmp = line.partition(string +
':')[2]
79 if tmp.startswith(
' '):
83 warning(
'Field empty on line ' + str(linecount))
90 if line.strip() ==
'':
93 if line.startswith(
'#')
and not decay_started:
95 if documentation_inprocess:
96 if 'EndDocumentation' in line:
97 documentation_inprocess =
False
98 documentation =
' '.join(documentation)
100 documentation += [line.strip(
'#')]
103 tmp = getfield(line,
'Documentation')
105 file2 = open(filename)
107 if 'EndDocumentation' in line2:
108 documentation_inprocess =
True
111 documentation += [tmp]
113 tmp = getfield(line,
'EventType')
118 fail([
'Failed parsing eventtype on line ' + str(linecount),
120 order += [
'EventType']
121 mesg(
'Eventtype found: ' + str(eventtype))
123 tmp = getfield(line,
'Descriptor')
126 order += [
'descriptor']
127 if '{,gamma}' in tmp:
128 warning(
'Please do not include radiative photons in the descriptor.'
131 tmp = getfield(line,
'NickName')
134 fail([
'NickName empty on line ' + str(linecount)])
135 elif not tmp == os.path.basename(filename).partition(
'.dec')[0]:
136 fail([
'NickName not the same as filename!'])
139 order += [
'nickname']
141 tmp = getfield(line,
'Cuts')
145 test_cuts = [
'None',
'DaughtersInBelleII']
146 if cuts
not in test_cuts:
147 warning(
'Unknown cuts <' + cuts +
'> on line ' + str(linecount) +
'. Please check.')
149 tmp = getfield(line,
'FullEventCuts')
152 order += [
'fulleventcuts']
154 tmp = getfield(line,
'ExtraOptions')
157 order += [
'extraopts']
159 tmp = getfield(line,
'PhysicsWG')
162 order += [
'physicswg']
164 tmp = getfield(line,
'Tested')
167 warning(
'File not tested! Please test the file!')
168 elif not tmp ==
'Yes':
169 warning(
'Unkown Tested state. Please use Yes or No.')
174 tmp = getfield(line,
'Responsible')
177 order += [
'responsible']
179 tmp = getfield(line,
'Email')
182 warning(
'Please use a correct email format.')
187 tmp = getfield(line,
'ParticleValue')
192 part = part.strip(
'"')
194 tmp2[part[6]] = part[1]
197 tmp = getfield(line,
'Date')
201 if not date / 10000 == time.gmtime().tm_year:
202 warning(
'Date is not from this year. Please use YYYYMMDD for date field. YYYY parsed:' +
203 str(date / 10000) +
' vs. current year: ' + str(time.gmtime().tm_year))
204 if date - 10000 * (date / 10000) > 1231:
205 warning(
'Cannot parse date. Please use YYYYMMDD for date field. MMDD parsed:' +
206 str(date - 10000 * (date / 10000)))
207 if date - 100 * (date / 100) > 31:
208 warning(
'Cannot parse date. Please use YYYYMMDD for date field. DD parsed:' +
209 str(date - 100 * (date / 100)))
211 warning(
'Cannot parse date. Please use YYYYMMDD for date field.'
213 elif not line ==
'' and not decay_started
and not Ended:
215 mesg(
'End of header.')
222 if not line.startswith(
'#'):
224 elements = line.partition(
'Alias')[2].strip().split()
225 alias[elements[0].strip()] = elements[1].strip()
226 if 'ChargeConj' in line:
227 elements = line.partition(
'ChargeConj')[2].strip().split()
228 chargeconj[elements[0].strip()] = elements[1].strip()
231 elements = line.partition(
'CDecay')[2].strip()
233 elif 'Decay' in line:
235 mother = line.partition(
'Decay ')[2].strip()
236 mesg(
'Found decay: ' + mother)
237 decay_inprocess =
True
240 if 'End' in line
and 'Enddecay' not in line:
242 decay_started =
False
245 if 'Enddecay' in line:
246 decay[mother] = current_decay
247 decay_inprocess =
False
252 line = line.strip().split()
258 warning(
'Branching fraction not a number on line: ' +
259 str(linecount) +
'. Skipping.')
261 for daug
in line[1:-1]:
262 if daug.strip(
';')
in settings.terminators:
265 elif daug.endswith(
';'):
266 warning(
'A new terminator found: ' + daug.strip(
';') +
'. Adding to list')
267 settings.terminators += [daug.strip(
';')]
272 elif daug
in chargeconj:
277 warning(
"You defined a charge conjugation without either particle being an alias. "
278 "Are you sure you know what you're doing on line " + str(linecount) +
'?')
282 warning(
'You defined an alias to particle ' + daug +
' called ' + k +
' but on line ' +
283 str(linecount) +
' you use the original particle. Is this what you want?')
285 if not line[-1].endswith(
';'):
286 warning(
'Line ' + str(linecount) +
' does not end with a ;')
287 current_decay += [(bf, dec)]
289 mesg(
'File parsed successfully.')
293 warning(
"Cannot proceed without eventtype. Please fix the eventtype so it's recognisable."
299 query(
'Checking general flag')
300 general = parttype / 10000000
302 parttype -= general * 10000000
306 mother = daug.partition(
'sig')[0]
310 if nickname.startswith(
'uubar'):
312 elif nickname.startswith(
'ddbar'):
314 elif nickname.startswith(
'ssbar'):
316 elif nickname.startswith(
'mixed'):
318 elif nickname.startswith(
'charged'):
320 elif nickname.startswith(
'charm'):
323 fail([
'Cannot find the signal particle and cannot determine the inclusive mode.'])
327 if 'B' in mother
or 'b0' in mother
or 'Upsilon' in mother
or 'chi_b' in mother:
329 elif 'D' in mother
or 'psi' in mother
or 'chi_c' in mother
or 'c+' in mother:
331 elif 'K_S0' in mother
or 'Lambda' in mother
or 'Sigma' in mother
or 'tau' in mother:
334 warning(
"Didn't recognise the mother particle. Check general flag manually.")
336 if not flag == general:
337 fail([
'General flag not compliant. Should be ' + str(flag) +
'.Please check.'])
340 newevtype += str(flag)
342 query(
'Checking selection flag')
343 selection = parttype / 1000000
344 parttype -= selection * 1000000
348 elif mother ==
'D-' or mother ==
'B0' or mother ==
'D+' or mother ==
'anti-B0':
350 elif mother ==
'D0' or mother ==
'anti-D0' or mother ==
'B+' or mother ==
'B-':
352 elif mother ==
'B_s0' or mother ==
'D_s-' or mother ==
'D_s+':
354 elif mother ==
'J/psi':
356 elif mother ==
'Lambda_b0' or mother ==
'Lambda_c+':
358 elif (
'Sigma_b' in mother
or 'chi_b' in mother
or 'Omega_b' in mother)
and general == 1:
360 elif (
'Upsilon' in mother
or 'chi_b' in mother)
and general == 1:
362 elif (
'D' in mother
and '*' in mother
or 'D_s1' in mother)
and general == 2:
364 elif (
'psi(2S)' in mother
or 'X_1(3872)' in mother
or 'h_c' in mother
or
365 'chi_c' in mother
or mother ==
'eta_c')
and general == 2:
370 if mother ==
'tau+' or mother ==
'tau-':
372 elif 'Lambda' in mother:
374 elif 'Sigma' in mother:
376 elif mother ==
'K_S0':
379 warning(
'General flag is 3 but mother particle is not recogniced - assuming minbias.'
383 warning(
'Cannot determine selection flag. Please check manually.')
385 if not flag == selection:
386 warning(
'Selection flag is not compliant, should be ' + str(flag) +
'. Please check.')
389 newevtype += str(flag)
391 query(
'Unfolding decay.')
395 current_decay = (decay[mother +
'sig'])[:]
397 for (bf2, dec2)
in current_decay:
401 newdecay.remove(daug)
402 for (bf2, dau2)
in decay[daug]:
404 for (bf3, dau3)
in decay[daug]:
406 newbf = bf * bf2 / norm
407 newdecay2 = newdecay[:] + dau2[:]
409 current_decay += [(newbf, newdecay2)]
416 for (bf, dec2)
in dec:
425 main_decay = [getmax(decay[mother +
'sig'])]
428 while not clean
and mother:
430 olddec = (main_decay[-1])[:]
431 for daug
in main_decay[-1]:
434 if daug
not in decay:
438 elif chargeconj[k] == daug:
440 if daug
not in decay:
441 warning(
'Aliased particle but cannot find its decay!: ' + daug)
442 newdec = [alias[daug]]
444 newdec = getmax(decay[daug])
448 main_decay += [olddec]
451 query(
'Checking the decay flag')
453 decayflag = parttype / 100000
454 parttype -= decayflag * 100000
461 for (bf, dec)
in current_decay:
463 for (bf2, dec2)
in current_decay:
468 if test_dec2 == test_dec1:
498 if not decayflag == flag:
499 fail([
'Decay flag is not compliant. Should be ' + str(flag) +
'. Please check'])
502 newevtype += str(flag)
504 query(
'Checking charm and lepton flag')
511 charmflag = parttype / 10000
512 parttype -= charmflag * 10000
516 for field
in [extraopts, cuts, fulleventcuts]:
517 if 'Electron' in field
or 'electron' in field:
519 if 'mu' in field
or 'Mu' in field:
521 if 'D0' in field
or 'Dmu' in field
or 'Ds' in field
or 'DS' in field
or 'DMass' in field
or 'DMu' in field:
526 for dec
in main_decay:
533 if daug ==
'e-' or daug ==
'e+':
536 if daug ==
'mu-' or daug ==
'mu+':
539 if (
'D' in daug
or '_c' in daug)
and 'chi_c' not in daug:
547 if 'psi' in daug
or 'chi_c' in daug:
562 if not flag == charmflag:
563 fail([
'Charm flag is not compliant. Should be :' + str(flag) +
'. Please check'])
566 newevtype += str(flag)
568 query(
'Checking track flag.')
569 trackflag = parttype / 1000
570 parttype -= trackflag * 1000
575 warning(
'Inclusive decay: Problem with settings the track flag. Check manually.'
577 if 'DiLepton' in fulleventcuts
or 'DiLepton' in cuts
or 'DiLepton' in extraopts:
579 for dec
in main_decay:
586 if daug
in settings.longlived:
589 if tracks > maxtracks:
592 if not trackflag == maxtracks:
593 fail([
'Track flag not compliant. Should be: ' + str(maxtracks) +
'. Please check.'])
596 newevtype += str(maxtracks)
598 query(
'Checking neutrals flag.')
599 neutrals = parttype / 100
600 parttype -= neutrals * 100
607 for dec
in main_decay:
611 if daug ==
'K_S0' or daug ==
'Lambda0' or mother ==
'K_S0' or mother ==
'Lambda0':
613 elif daug ==
'pi0' or daug ==
'eta':
619 for i
in range(len(main_decay)):
620 if 'gamma' in main_decay[i]:
623 for daug
in main_decay[i - 1]:
627 if daug2 ==
'pi0' or daug2 ==
'eta':
628 if daug
not in main_decay[i]:
645 if not flag == neutrals:
646 fail([
'Neutrals flag not compliant. Should be ' + str(flag) +
'. Please check.'])
649 newevtype += str(flag)
651 query(
'Checking the extra and user for duplicity .')
655 warning(
'Cannot parse decfiles webpage')
656 settings.use_url =
False
658 for (k, v)
in zippednos:
659 if filename.partition(
'=')[0] == v.partition(
'=')[0]
and not eventtype / 10 == k / 10:
660 warning(
'The decfile: ' + v +
':' + str(k) +
' should contain the same decay, therefore the first 7 '
661 'digits of the eventtype should match. Please check and use the same extra flag.')
664 warning(
'Error: ' + v +
' has this eventtype already.')
666 if k / 10 == eventtype / 10
and not os.path.basename(filename).partition(
'=')[0] == v.partition(
'=')[0]:
667 warning(
'The decfile: ' + v +
':' + str(k) +
' uses this extra flag, but the decay seems different. '
668 'Please check and use a unique extra flag.')
674 warning(
'Cannot parse obsoletes trac file.')
675 settings.use_url =
False
677 if str(eventtype)
in obsnos:
678 warning(
'The eventtype is obsolete on the line ' +
679 str(obsnos.index(str(eventtype)) + 1) +
' in: ' +
683 if not settings.use_url:
684 filelist = os.listdir(dkfilespath)
687 for filen
in filelist:
688 if filen.endswith(
'.dec'):
689 file = open(dkfilespath +
'/' + filen)
691 if 'EventType: ' in line:
693 newtype = int(line.partition(
'EventType: ')[2].strip())
697 if filen.partition(
'=')[0] == filename.partition(
'='):
698 if not newtype / 10 == eventtype / 10:
699 warning(
'The decfile: ' + filen +
':' + str(newtype) +
' should contain the same decay, therefore the first 7 '
700 'digits of the eventtype should match. Please check and use the same extra flag.')
703 if newtype == eventtype:
704 warning(
'Error: ' + filen +
' has this eventtype already.')
707 if settings.obsoletepath:
708 obsfile = open(settings.obsoletepath +
'/table_obsolete.sql')
711 if int(line.partition(
'EVTTYPEID = ')[2].partition(
', DESCRIPTION')[0]) == eventtype:
712 warning(
'The eventtype is obsolete on the following line in: ' + settings.obsoletepath +
'/table_obsolete.sql')
716 extraflag = eventtype / 10
717 extraflag = eventtype - extraflag * 10
718 if 'DaughtersInBelleII' not in cuts
and extraflag
and cuts == 0:
719 warning(
'Your cuts are not empty, please set your userflag to greater or equal to 1.'
722 if cuts == [
'None']
and extraflag != 0:
723 warning(
"Your cuts are empty, your user flag should be 0 unless that's taken. Please check."
730 mesg(
'Eventtype constructed: ' + newevtype +
'XX')
732 query(
'Checking nickname.')
735 if not nickname == os.path.basename(filename).partition(
'.dec')[0]:
736 faillist += [
'Filename not the same as nickname! Fix.']
738 nick = nickname.partition(
'=')
739 if not nick[1] ==
'=' and not cuts == []:
741 [
'The = sign not found in the nickname while cuts are present. Check nickname conventions and fix.'
743 warning(
'The = sign not found in the nickname while cuts are present. Check nickname conventions and fix.'
746 if 'DaughtersInBelleII' in cuts
and 'DecProdCut' not in nick[2].split(
','):
748 [
'You have decay angular acceptance cut in Cuts but not in the nickname.'
757 if not len(nick[0].split(
',')) > 1
and mother:
758 warning(
'Found only one decay level in the nickname - highly unusual, you should probably use at least two.'
761 if len(nick[2].split(
',')) < len(cuts.split(
',')):
762 warning(
'You have more cuts than declared in the nickname. Please check.')
764 query(
'Checking the Physics WG.')
765 if physicswg
not in settings.groups:
766 fail([
'The group /' + physicswg +
'/ is not known. Please use one of the following:',
772 query(
'Building descriptor.')
775 for (bf, dec)
in decay[mother +
'sig']:
778 for (bf, dec)
in decay[mother +
'sig']:
781 descript = [mother] + [
'->'] + curdec
785 for daug
in descript:
790 for (bf, dec)
in decay[daug]:
793 for (bf, dec)
in decay[daug]:
796 ind = descript.index(daug)
797 descript.remove(daug)
798 if daug
not in alias:
799 warning(
'You decay a particle: [' + daug +
800 '] without aliasing it first. Step aborted.')
805 toadd = [
'(', daug,
'->'] + curdec + [
')']
808 descript.insert(ind, el)
815 descript =
'[' +
' '.join(descript) +
']'
816 descript = descript.replace(
'( ',
'(')
817 descript = descript.replace(
' )',
')')
825 query(
'Checking descriptor.')
827 decr_old = descriptor.partition(
'[')[2].partition(
']')[0].split()
828 decr_new = descript.partition(
'[')[2].partition(
']')[0].split()
836 fail([
'Descriptor not matched. Please check the old one:', descriptor,
837 '\nAnd the one built by the parser: ', descript])
838 for mes
in descriptcheck.mesgdict:
842 print(daug, decay[daug])
844 print(
'Main decay chain:')
845 for dec
in main_decay:
848 sys.exit(
'Decfile check complete.')