13 Decay File Parser to check whether a decay file is correctly defined
20 from colours
import mesg, query, fail, done, warning
23 mesg(
'Starting the decfile check')
24 query(
'Opening decfile')
26 fail([
'Please pass the decfile as the first argument.'])
29 filename = sys.argv[1]
30 dkfilespath = os.path.dirname(os.path.abspath(sys.argv[0])) +
'/' \
31 + settings.dkfilespath
33 if not os.path.exists(filename):
34 fail([
'The file does not exist'])
36 elif not os.path.isfile(filename):
38 fail([
'The path does not point to a regular file.'])
43 fail([
'Unknown error opening file.'])
48 documentation_inprocess =
False
67 decay_inprocess =
False
80 def getfield(line, string):
82 if string +
':' in line:
83 query(
'Now parsing: ' + string)
84 tmp = line.partition(string +
':')[2]
86 if tmp.startswith(
' '):
90 warning(
'Field empty on line ' + str(linecount))
97 if line.strip() ==
'':
100 if line.startswith(
'#')
and not decay_started:
102 if documentation_inprocess:
103 if 'EndDocumentation' in line:
104 documentation_inprocess =
False
105 documentation =
' '.join(documentation)
107 documentation += [line.strip(
'#')]
110 tmp = getfield(line,
'Documentation')
112 file2 = open(filename)
114 if 'EndDocumentation' in line2:
115 documentation_inprocess =
True
118 documentation += [tmp]
120 tmp = getfield(line,
'EventType')
124 except BaseException:
125 fail([
'Failed parsing eventtype on line ' + str(linecount),
127 order += [
'EventType']
128 mesg(
'Eventtype found: ' + str(eventtype))
130 tmp = getfield(line,
'Descriptor')
133 order += [
'descriptor']
134 if '{,gamma}' in tmp:
136 'Please do not include radiative photons in the descriptor.')
138 tmp = getfield(line,
'NickName')
141 fail([
'NickName empty on line ' + str(linecount)])
142 elif not tmp == os.path.basename(filename).partition(
'.dec')[0]:
143 fail([
'NickName not the same as filename!'])
146 order += [
'nickname']
148 tmp = getfield(line,
'Cuts')
152 test_cuts = [
'None',
'DaughtersInBelleII']
153 if cuts
not in test_cuts:
161 tmp = getfield(line,
'FullEventCuts')
164 order += [
'fulleventcuts']
166 tmp = getfield(line,
'ExtraOptions')
169 order += [
'extraopts']
171 tmp = getfield(line,
'PhysicsWG')
174 order += [
'physicswg']
176 tmp = getfield(line,
'Tested')
179 warning(
'File not tested! Please test the file!')
180 elif not tmp ==
'Yes':
181 warning(
'Unkown Tested state. Please use Yes or No.')
186 tmp = getfield(line,
'Responsible')
189 order += [
'responsible']
191 tmp = getfield(line,
'Email')
194 warning(
'Please use a correct email format.')
199 tmp = getfield(line,
'ParticleValue')
204 part = part.strip(
'"')
206 tmp2[part[6]] = part[1]
209 tmp = getfield(line,
'Date')
213 if not date / 10000 == time.gmtime().tm_year:
214 warning(
'Date is not from this year. Please use YYYYMMDD for date field. YYYY parsed:' +
215 str(date / 10000) +
' vs. current year: ' + str(time.gmtime().tm_year))
216 if date - 10000 * (date / 10000) > 1231:
217 warning(
'Cannot parse date. Please use YYYYMMDD for date field. MMDD parsed:' +
218 str(date - 10000 * (date / 10000)))
219 if date - 100 * (date / 100) > 31:
220 warning(
'Cannot parse date. Please use YYYYMMDD for date field. DD parsed:' +
221 str(date - 100 * (date / 100)))
222 except BaseException:
223 warning(
'Cannot parse date. Please use YYYYMMDD for date field.'
225 elif not line ==
'' and not decay_started
and not Ended:
227 mesg(
'End of header.')
234 if not line.startswith(
'#'):
236 elements = line.partition(
'Alias')[2].strip().split()
237 alias[elements[0].strip()] = elements[1].strip()
238 if 'ChargeConj' in line:
239 elements = line.partition(
'ChargeConj')[2].strip().split()
240 chargeconj[elements[0].strip()] = elements[1].strip()
243 elements = line.partition(
'CDecay')[2].strip()
245 elif 'Decay' in line:
247 mother = line.partition(
'Decay ')[2].strip()
248 mesg(
'Found decay: ' + mother)
249 decay_inprocess =
True
252 if 'End' in line
and 'Enddecay' not in line:
254 decay_started =
False
257 if 'Enddecay' in line:
258 decay[mother] = current_decay
259 decay_inprocess =
False
264 line = line.strip().split()
269 except BaseException:
270 warning(
'Branching fraction not a number on line: ' +
271 str(linecount) +
'. Skipping.')
273 for daug
in line[1:-1]:
274 if daug.strip(
';')
in settings.terminators:
277 elif daug.endswith(
';'):
279 'A new terminator found: ' +
282 settings.terminators += [daug.strip(
';')]
287 elif daug
in chargeconj:
293 "You defined a charge conjugation without either particle being an alias. "
294 "Are you sure you know what you're doing on line " + str(linecount) +
'?')
299 'You defined an alias to particle ' +
305 ' you use the original particle. Is this what you want?')
307 if not line[-1].endswith(
';'):
311 ' does not end with a ;')
312 current_decay += [(bf, dec)]
314 mesg(
'File parsed successfully.')
318 warning(
"Cannot proceed without eventtype. Please fix the eventtype so it's recognisable."
324 query(
'Checking general flag')
325 general = int(str(parttype)[0])
330 mother = daug.partition(
'sig')[0]
334 if nickname.startswith(
'uubar'):
336 elif nickname.startswith(
'ddbar'):
338 elif nickname.startswith(
'ssbar'):
340 elif nickname.startswith(
'mixed'):
342 elif nickname.startswith(
'charged'):
344 elif nickname.startswith(
'charm'):
347 fail([
'Cannot find the signal particle and cannot determine the inclusive mode.'])
351 if 'B' in mother
or 'b0' in mother
or 'Upsilon' in mother
or 'chi_b' in mother:
353 elif 'D' in mother
or 'psi' in mother
or 'chi_c' in mother
or 'c+' in mother:
355 elif 'K_S0' in mother
or 'Lambda' in mother
or 'Sigma' in mother
or 'tau' in mother:
358 warning(
"Didn't recognise the mother particle. Check general flag manually.")
360 if not flag == general:
361 fail([
'General flag not compliant. Should be ' + str(flag) +
'. Please check.'])
364 newevtype += str(flag)
366 query(
'Checking selection flag')
367 selection = int(str(parttype)[1])
371 elif mother ==
'D-' or mother ==
'B0' or mother ==
'D+' or mother ==
'anti-B0':
373 elif mother ==
'D0' or mother ==
'anti-D0' or mother ==
'B+' or mother ==
'B-':
375 elif mother ==
'B_s0' or mother ==
'D_s-' or mother ==
'D_s+':
377 elif mother ==
'J/psi':
379 elif mother ==
'Lambda_b0' or mother ==
'Lambda_c+':
381 elif (
'Sigma_b' in mother
or 'chi_b' in mother
or 'Omega_b' in mother)
and general == 1:
383 elif (
'Upsilon' in mother
or 'chi_b' in mother)
and general == 1:
385 elif (
'D' in mother
and '*' in mother
or 'D_s1' in mother)
and general == 2:
387 elif (
'psi(2S)' in mother
or 'X_1(3872)' in mother
or 'h_c' in mother
or
388 'chi_c' in mother
or mother ==
'eta_c')
and general == 2:
393 if mother ==
'tau+' or mother ==
'tau-':
395 elif 'Lambda' in mother:
397 elif 'Sigma' in mother:
399 elif mother ==
'K_S0':
403 'General flag is 3 but mother particle is not recogniced - assuming minbias.')
406 warning(
'Cannot determine selection flag. Please check manually.')
408 if not flag == selection:
410 'Selection flag is not compliant, should be ' +
415 newevtype += str(flag)
417 query(
'Unfolding decay.')
421 current_decay = (decay[mother +
'sig'])[:]
423 for (bf2, dec2)
in current_decay:
427 newdecay.remove(daug)
428 for (bf2, dau2)
in decay[daug]:
430 for (bf3, dau3)
in decay[daug]:
432 newbf = bf * bf2 / norm
433 newdecay2 = sorted(newdecay[:] + dau2[:])
434 current_decay += [(newbf, newdecay2)]
441 for (bf, dec2)
in dec:
450 main_decay = [getmax(decay[mother +
'sig'])]
453 while not clean
and mother:
455 olddec = (main_decay[-1])[:]
456 for daug
in main_decay[-1]:
459 if daug
not in decay:
463 elif chargeconj[k] == daug:
465 if daug
not in decay:
466 warning(
'Aliased particle but cannot find its decay!: ' + daug)
467 newdec = [alias[daug]]
469 newdec = getmax(decay[daug])
473 main_decay += [olddec]
476 query(
'Checking the decay flag')
478 decayflag = int(str(parttype)[2])
485 for (bf, dec)
in current_decay:
487 for (bf2, dec2)
in current_decay:
492 if test_dec2 == test_dec1:
521 if not decayflag == flag:
522 fail([
'Decay flag is not compliant. Should be ' + str(flag) +
'. Please check'])
525 newevtype += str(flag)
527 query(
'Checking charm and lepton flag')
534 charmflag = int(str(parttype)[3])
538 for field
in [extraopts, cuts, fulleventcuts]:
539 if 'Electron' in field
or 'electron' in field:
541 if 'mu' in field
or 'Mu' in field:
543 if 'D0' in field
or 'Dmu' in field
or 'Ds' in field
or 'DS' in field
or 'DMass' in field
or 'DMu' in field:
548 for dec
in main_decay:
555 if daug ==
'e-' or daug ==
'e+':
558 if daug ==
'mu-' or daug ==
'mu+':
561 if (
'D' in daug
or '_c' in daug)
and 'chi_c' not in daug:
569 if 'psi' in daug
or 'chi_c' in daug:
584 if not flag == charmflag:
585 fail([
'Charm flag is not compliant. Should be ' + str(flag) +
'. Please check'])
588 newevtype += str(flag)
590 query(
'Checking track flag.')
591 trackflag = int(str(parttype)[4])
596 warning(
'Inclusive decay: Problem with settings the track flag. Check manually.'
598 if 'DiLepton' in fulleventcuts
or 'DiLepton' in cuts
or 'DiLepton' in extraopts:
600 for dec
in main_decay:
607 if daug
in settings.longlived:
610 if tracks > maxtracks:
613 if not trackflag == maxtracks:
614 fail([
'Track flag not compliant. Should be ' +
615 str(maxtracks) +
'. Please check.'])
618 newevtype += str(maxtracks)
620 query(
'Checking neutrals flag.')
621 neutrals = int(str(parttype)[5])
628 for dec
in main_decay:
632 if daug ==
'K_S0' or daug ==
'Lambda0' or mother ==
'K_S0' or mother ==
'Lambda0':
634 elif daug ==
'pi0' or daug ==
'eta':
640 for i
in range(len(main_decay)):
641 if 'gamma' in main_decay[i]:
644 for daug
in main_decay[i - 1]:
648 if daug2 ==
'pi0' or daug2 ==
'eta':
649 if daug
not in main_decay[i]:
666 if not flag == neutrals:
667 fail([
'Neutrals flag not compliant. Should be ' + str(flag) +
'. Please check.'])
670 newevtype += str(flag)
672 query(
'Checking the extra and user for duplicity .')
674 if not settings.use_url:
675 filelist = os.listdir(dkfilespath)
678 for filen
in filelist:
679 if filen.endswith(
'.dec'):
680 file = open(dkfilespath +
'/' + filen)
682 if 'EventType: ' in line:
684 newtype = int(line.partition(
'EventType: ')[2].strip())
686 except BaseException:
688 if filen.partition(
'=')[0] == filename.partition(
'='):
689 if not newtype / 10 == eventtype / 10:
695 ' should contain the same decay, therefore the first 7 '
696 'digits of the eventtype should match. Please check and use the same extra flag.')
699 if newtype == eventtype:
700 warning(
'Error: ' + filen +
' has this eventtype already.')
703 if settings.obsoletepath:
704 obsfile = open(dkfilespath +
'/' + settings.obsoletepath +
'/table_obsolete.sql')
707 if int(line.partition(
'EVTTYPEID = ')[2].partition(
708 ', DESCRIPTION')[0]) == eventtype:
710 'The eventtype is obsolete on the following line in: ' +
711 settings.obsoletepath +
712 '/table_obsolete.sql')
716 extraflag = eventtype / 10
717 extraflag = eventtype - extraflag * 10
718 if 'DaughtersInBelleII' not in cuts
and extraflag
and cuts == 0:
720 '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 +
767 '/ is not known. Please use one of the following:', settings.groups])
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.')
def convertToList(stringA)
def compareList(listA, listB)