Belle II Software  release-06-02-00
CreateProdScripts.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 # create an mc production file from a decay file
13 # warning: this script is under development
14 
15 from optparse import OptionParser, OptionValueError
16 import glob
17 import time
18 import sys
19 import logging
20 import re
21 import os
22 version = 'v1'
23 
24 bkk_first = True
25 eventid_inbkk = []
26 sql_first = True
27 eventid_insql = []
28 list_of_obsoletes = []
29 exit_status = 0
30 list_of_wg = ['SL', 'EWP', 'TCPV', 'HAD', 'CHARM', 'ONIA', 'TAU']
31 
32 
33 class GenericOptionFile(object):
34 
35  """
36  Class to write in an option file
37  """
38 
39  def __init__(self):
40  """
41  Constructor.
42  Parameters:
43  filename name of the file
44  f alternative name of the file
45  """
46 
47  self.filenamefilename = None
48 
49  self.ff = None
50 
51  def __del__(self):
52  """
53  Destructor.
54  """
55  self.CloseClose()
56 
57  def Close(self):
58  """
59  Close file.
60  """
61  if self.ff:
62  self.ff.close()
63 
64  def OptionFileName(self):
65  """
66  Set option file name.
67  """
68  return self.filenamefilename
69 
70  def SetFileName(self, filename):
71  """
72  Set file name.
73  """
74  self.filenamefilename = os.path.normpath(filename + self.suffix)
75 
76  def Open(self):
77  """
78  Open file.
79  """
80  if self.filenamefilename:
81  self.ff = open(self.filenamefilename, 'w')
82 
83  def Write(self, lines):
84  """
85  Write the lines in the file.
86  """
87 
88  self.ff.writelines([line + '\n' for line in lines])
89 
90  def WriteHeader(self, eventtype, descriptor):
91  """
92  Write header of .dec file.
93  """
94  timeString = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
95  lines = [
96  f"{self.comment} file {self.filename} generated: {timeString}",
97  self.comment,
98  f"{self.comment} Event Type: {eventtype}",
99  self.comment,
100  f"{self.comment} ASCII decay Descriptor: {descriptor}",
101  self.comment
102  ]
103 
104  self.WriteWrite(lines)
105 
106  def AddExtraOptions(self, eventtype):
107  """
108  Adds extra options.
109  """
110  self.AddInclude(eventtype.ExtraOptions())
111 
112  def AddEventTypeNumber(self, eventtype):
113  """
114  Adds the Event Type Number.
115  """
116  self.AddOptionValue('GenerationEventType', eventtype.EventTypeNumber())
117 
118  def AddEvtGenUserDecayFile(self, eventtype):
119  """
120  Set the EvtGen .dec file.
121  """
122  self.AddOptionValue('EvtGenUserDecayFile',
123  '"$DECFILESROOT/dec/{0}.dec"'.format(eventtype.DecayName()))
124 
125  def AddDecayOptions(self, eventtype):
126  """
127  Specify options for .dec file.
128  """
129  [self.AddOptionValue('ToolSvc.{0}Decay.{1}'.format(
130  eventtype.DecayEngine(), eventtype.DecayOptions().split()[2 * i]),
131  eventtype.DecayOptions().split()[2 * i + 1])
132  for i in range(len(eventtype.DecayOptions().split()) / 2)]
133 
134 
136 
137  """
138  Class to read generic option file in .txt format.
139 
140  Attributes:
141  comment comment string
142  suffix suffix string
143  true_string true string
144  list_begin open list parenthesis
145  list_end close list parenthesis
146 
147  """
148 
149  comment = '//'
150 
151  suffix = '.opts'
152 
153  true_string = 'true'
154 
155  list_begin = '{'
156 
157  list_end = '}'
158 
159  def AddOptionValue(self, option, value, substitute=False):
160  """
161  Set the value of option.
162  """
163  self.WriteWrite(['{0} = {1};'.format(option, value)])
164 
165  def AddInclude(self, filename):
166  """
167  Add include statements.
168  """
169  self.WriteWrite(['#include "$DECFILESROOT/prod/{0}.py"'.format(filename)])
170 
171  def IncreaseOptionValue(self, option, value):
172  """
173  Add option string.
174  """
175  self.WriteWrite(['{0} += {1};'.format(option, value)])
176 
177 
179 
180  """
181  Class to read generic option file in .py format.
182 
183  Attributes:
184  comment comment string
185  suffix suffix string
186  true_string true string
187  list_begin open list parenthesis
188  list_end close list parenthesis
189 
190  """
191 
192  comment = '#'
193 
194  suffix = '.py'
195 
196  true_string = 'True'
197 
198  list_begin = '['
199 
200  list_end = ']'
201 
202  def __init__(self):
203  """
204  Constructor.
205 
206  Attributes:
207  list_algorithm list of algorithms
208  list_tool list of tools
209  """
210 
211  self.list_algorithmlist_algorithm = []
212 
213  self.list_toollist_tool = []
214  super(PythonOptionFile, self).__init__()
215 
216  def AddOptionValue(self, option, value, substitute=False):
217  """
218  Add option string.
219  """
220  value = value.replace('{', '[')
221  value = value.replace('}', ']')
222  if substitute:
223  value = value.replace('true', 'True')
224  value = value.replace('false', 'False')
225  self.WriteWrite(['{0} = {1}'.format(option, value)])
226 
227  def IncreaseOptionValue(self, option, value):
228  """
229  Add option string.
230  """
231  option = self.ConfigureToolAndAlgo(option)
232  self.WriteWrite(['{0} += {1}'.format(option, value)])
233 
234 
235 class EventType:
236 
237  """
238  Class to hold event type information.
239 
240  Attributes:
241  MandatoryKeywords list of mandatory keywords for file description
242  OptionalKeywords list of optional keywords for file description
243  """
244 
245  MandatoryKeywords = [
246  'EventType',
247  'Descriptor',
248  'NickName',
249  'Cuts',
250  'Documentation',
251  'PhysicsWG',
252  'Tested',
253  'Responsible',
254  'Email',
255  'Date',
256  ]
257 
258  OptionalKeywords = [
259  'Sample',
260  'ExtraOptions',
261  'DecayOptions',
262  'DecayEngine',
263  'CutsOptions',
264  'Configuration',
265  'ParticleType',
266  'Momentum',
267  'MomentumRange',
268  'Id',
269  'Production',
270  'FullEventCuts',
271  'ParticleValue',
272  'ParticleTable',
273  'InsertPythonCode',
274  ]
275 
276  def __init__(self, filename, remove, technology):
277  """
278  Constructor.
279 
280  Attributes:
281  DecayFileName name of decay file
282  KeywordDictionary dictionary of keywords
283  remove "remove file" flag - force removing the option file and create a new one
284  OptionFile flag for existence of option file
285  technology specify the langauge of the script
286  """
287 
288 
289  self.DecayFileNameDecayFileName = os.path.normpath(filename)
290 
291  self.KeywordDictionaryKeywordDictionary = {}
292 
293  self.removeremove = remove
294 
295  self.OptionFileOptionFile = None
296 
297  self.technologytechnology = technology
298 
299  def DecodeDecayFile(self):
300  """
301  Operates deconding of decay file.
302  """
303  fullstring = ''
304  with open(self.DecayFileNameDecayFileName, 'rb') as f:
305  for line in f:
306  # Keep only lines starting with '#'
307  if line.startswith('# '):
308  line = line.replace('# ', '', 1)
309  fullstring += line
310  elif line.startswith('#'):
311  line = line.lstrip('#')
312  fullstring += line
313 
314  pattern1 = r'(?m)(\w+): (.+)'
315  pattern2 = r'(Documentation):((?s).*)EndDocumentation'
316  pattern3 = r'(InsertPythonCode):((?s).*)EndInsertPythonCode'
317  matchObj1 = re.findall(pattern1, fullstring)
318  matchObj2 = re.findall(pattern2, fullstring)
319  matchObj3 = re.findall(pattern3, fullstring)
320  if matchObj1 or matchObj2 or matchObj3:
321  for matchobj in matchObj1 + matchObj2 + matchObj3:
322  self.KeywordDictionaryKeywordDictionary[matchobj[0]] = matchobj[1]
323  keystodelete = []
324  # delete keys found if Python Code
325  if matchObj3:
326  matchObj = re.findall(pattern1,
327  self.KeywordDictionaryKeywordDictionary['InsertPythonCode'])
328  if matchObj:
329  for matchobj in matchObj:
330  keystodelete.append(matchobj[0])
331  # remove leading and ending spaces, except for python code
332  for (k, v) in self.KeywordDictionaryKeywordDictionary.items():
333  if k != 'InsertPythonCode':
334  self.KeywordDictionaryKeywordDictionary[k] = v.rstrip(' \n').lstrip(' \n')
335  if self.KeywordDictionaryKeywordDictionary[k] == '':
336  keystodelete.append(k)
337  for k in keystodelete:
338  del self.KeywordDictionaryKeywordDictionary[k]
339 
340  def Validate(self, obsoletes):
341  """
342  Check for the presence of mandatory keywords.
343  """
344  missing_mandatory = set(self.MandatoryKeywordsMandatoryKeywords) \
345  - set(self.KeywordDictionaryKeywordDictionary.keys())
346  if len(missing_mandatory) != 0:
347  logging.error('%s.dec is missing mandatory keywords: %s',
348  self.DecayNameDecayName(), [key for key in missing_mandatory])
349  raise SyntaxWarning
350  unknown_keywords = set(self.KeywordDictionaryKeywordDictionary.keys()) \
351  - (set(self.MandatoryKeywordsMandatoryKeywords) | set(self.OptionalKeywordsOptionalKeywords))
352  if len(unknown_keywords) != 0:
353  logging.error('%s.dec contains unknown keywords: %s',
354  self.DecayNameDecayName(), [key for key in unknown_keywords])
355  raise SyntaxWarning
356 
357  # check if the nickname is correct
358  if self.NickNameNickName() != self.DecayNameDecayName():
359  logging.error(
360  'In %s, the nickname %s is not equal to the name of the file %s.',
361  self.DecayFileNameDecayFileName,
362  self.KeywordDictionaryKeywordDictionary['NickName'],
363  self.DecayNameDecayName())
364  raise UserWarning
365 
366  # check if the date format is correct
367  try:
368  thetime = time.strptime(self.DateDate(), '%Y%m%d')
369  except ValueError:
370  logging.error(
371  'In %s, the date format is not correct, it should be YYYYMMDD instead of %s.',
372  self.DecayFileNameDecayFileName,
373  self.DateDate())
374  raise UserWarning
375 
376  # check physics wg name
377  if self.PhysicsWGPhysicsWG() not in list_of_wg:
378  logging.error('In %s, the name of the WG is not correct: %s.',
379  self.DecayFileNameDecayFileName, self.PhysicsWGPhysicsWG())
380 
381  # check the event type does not start with 0
382  if self.EventTypeNumberEventTypeNumber()[0] == '0':
383  logging.error('The EventType is not correct in %s.',
384  self.DecayFileNameDecayFileName)
385  logging.error('It cannot start with 0.')
386  raise UserWarning
387 
388  # check the event type has at least 8 digits
389  if len(self.EventTypeNumberEventTypeNumber()) < 8:
390  logging.error('The EventType is not correct in %s.',
391  self.DecayFileNameDecayFileName)
392  logging.error('It must have at least 8 digits.')
393  raise UserWarning
394 
395  # check if the event is obsolete
396  if self.EventTypeNumberEventTypeNumber() in obsoletes:
397  logging.error(
398  'The EventType %s is in use in the obsolete list, please change it.',
399  self.EventTypeNumberEventTypeNumber())
400  raise UserWarning
401 
402  # check Tested is equal to Yes or No
403  self.KeywordDictionaryKeywordDictionary['Tested'] = self.KeywordDictionaryKeywordDictionary['Tested'].lower(
404  )
405  if self.KeywordDictionaryKeywordDictionary['Tested'] != 'yes' and self.KeywordDictionaryKeywordDictionary['Tested'] != 'no':
406  logging.error(
407  'In %s, Tested should be equal to Yes or No',
408  self.DecayNameDecayName())
409  raise UserWarning
410 
411  # check that the file has been tested (check can be disabled with
412  # --force option)
413  if self.KeywordDictionaryKeywordDictionary['Tested'] == 'no':
414  logging.error('The decay file %s has not been tested',
415  self.DecayNameDecayName())
416  raise SyntaxWarning
417 
418  def EventTypeNumber(self):
419  """
420  Returns event type number.
421  """
422  return self.KeywordDictionaryKeywordDictionary['EventType'].replace(' ', '')
423 
424  def G(self):
425  """
426  Returns general flag of event type.
427  """
428  return self.EventTypeNumberEventTypeNumber()[0]
429 
430  def S(self):
431  """
432  Returns selection flag of event type.
433  """
434  return self.EventTypeNumberEventTypeNumber()[1]
435 
436  def D(self):
437  """
438  Returns the decay flag of even type.
439  """
440  return self.EventTypeNumberEventTypeNumber()[2]
441 
442  def C(self):
443  """
444  Returns the charm flag of even type.
445  """
446  return self.EventTypeNumberEventTypeNumber()[3]
447 
448  def L(self):
449  """
450  Returns the lepton flag of even type.
451  """
452  return self.EventTypeNumberEventTypeNumber()[4]
453 
454  def T(self):
455  """
456  Returns the track flag of even type.
457  """
458  return self.EventTypeNumberEventTypeNumber()[5]
459 
460  def N(self):
461  """
462  Returns the neutral flag of even type.
463  """
464  return self.EventTypeNumberEventTypeNumber()[6]
465 
466  def K(self):
467  """
468  Returns the neutral Kaons flag of even type.
469  """
470  return self.EventTypeNumberEventTypeNumber()[7]
471 
472  def E(self):
473  """
474  Returns the extra flag of even type.
475  """
476  return self.EventTypeNumberEventTypeNumber()[8]
477 
478  def U(self):
479  """
480  Returns the user flag of even type.
481  """
482  return self.EventTypeNumberEventTypeNumber()[9]
483 
484  def IsSpecialSource(self):
485  """
486  Check whether it is a special source.
487  """
488  return self.EventTypeNumberEventTypeNumber()[0] == '6' and self.EventTypeNumberEventTypeNumber()[3] \
489  == '5' or self.EventTypeNumberEventTypeNumber()[0] == '6' \
490  and self.EventTypeNumberEventTypeNumber()[3] == '4'
491 
492  def SetOptionFileName(self, filename=None):
493  """
494  Set name of option file.
495  """
496  if 'Text' in self.technologytechnology:
497  self.OptionFileOptionFile = TextOptionFile()
498  else:
499  self.OptionFileOptionFile = PythonOptionFile()
500 
501  if not filename:
502  filename = '{0}/prod/{1}'.format(
503  os.environ['DECFILESROOT'], self.EventTypeNumberEventTypeNumber())
504 
505  self.OptionFileOptionFile.SetFileName(filename)
506  if os.path.exists(self.OptionFileOptionFile.OptionFileName()):
507  if self.removeremove:
508  os.remove(self.OptionFileOptionFile.OptionFileName())
509  else:
510  logging.warning('The file %s already exists.',
511  self.OptionFileOptionFile.OptionFileName())
512  logging.warning(
513  'To overwrite it, you should remove it first or run with the --remove option.')
514  raise UserWarning
515  self.OptionFileOptionFile.Open()
516 
517  def DecayDescriptor(self):
518  """
519  Returns decay descriptor.
520  """
521  return self.KeywordDictionaryKeywordDictionary['Descriptor']
522 
524  """
525  Check if there is python code to be inserted.
526  """
527  return 'InsertPythonCode' in self.KeywordDictionaryKeywordDictionary
528 
530  """
531  Returns the python code to be inserted.
532  """
533  return self.KeywordDictionaryKeywordDictionary['InsertPythonCode']
534 
535  def HasExtraOptions(self):
536  """
537  Check if it has extra options.
538  """
539  return 'ExtraOptions' in self.KeywordDictionaryKeywordDictionary
540 
541  def ExtraOptions(self):
542  """
543  Returns the extra options.
544  """
545  return self.KeywordDictionaryKeywordDictionary['ExtraOptions']
546 
547  def HasDecayEngine(self):
548  """
549  Check if decay engine has been specified.
550  """
551  return 'DecayEngine' in self.KeywordDictionaryKeywordDictionary
552 
553  def DecayEngine(self):
554  """
555  Returns the decay engine.
556  """
557  return self.KeywordDictionaryKeywordDictionary['DecayEngine']
558 
559  def HasDecayOptions(self):
560  """
561  Check if decay options have been specified.
562  """
563  return 'DecayOptions' in self.KeywordDictionaryKeywordDictionary
564 
565  def DecayOptions(self):
566  """
567  Returns the decay options.
568  """
569  return self.KeywordDictionaryKeywordDictionary['DecayOptions']
570 
571  def HasParticleTable(self):
572  """
573  Check whether particle table already exists.
574  """
575  return 'ParticleTable' in self.KeywordDictionaryKeywordDictionary
576 
577  def ParticleTable(self):
578  """
579  Return particle table.
580  """
581  return self.KeywordDictionaryKeywordDictionary['ParticleTable']
582 
583  def HasParticleValue(self):
584  """
585  Check if particle value parameter has been specified.
586  """
587  return 'ParticleValue' in self.KeywordDictionaryKeywordDictionary
588 
589  def ParticleValue(self):
590  """
591  Returns particle value.
592  """
593  return self.KeywordDictionaryKeywordDictionary['ParticleValue']
594 
595  def HasConfiguration(self):
596  """
597  Check if configuration is present in keyword dictionary.
598  """
599  return 'Configuration' in self.KeywordDictionaryKeywordDictionary
600 
601  def Configuration(self):
602  """
603  Returns configuration.
604  """
605  return self.KeywordDictionaryKeywordDictionary['Configuration'].split()
606 
607  def HasParticleType(self):
608  """
609  Check if Particle Type is present in keyword dictionary.
610  """
611  return 'ParticleType' in self.KeywordDictionaryKeywordDictionary
612 
613  def ParticleType(self):
614  """
615  Returns Particle Type.
616  """
617  return self.KeywordDictionaryKeywordDictionary['ParticleType'].split()
618 
619  def HasMomentum(self):
620  """
621  Check if momentum is present in keyword dictionary.
622  """
623  return 'Momentum' in self.KeywordDictionaryKeywordDictionary
624 
625  def Momentum(self):
626  """
627  Returns momentum.
628  """
629  return self.KeywordDictionaryKeywordDictionary['Momentum'].split()
630 
631  def HasMomentumRange(self):
632  """
633  Check if momentum range is present in keyword dictionary.
634  """
635  return 'MomentumRange' in self.KeywordDictionaryKeywordDictionary
636 
637  def MomentumRange(self):
638  """
639  Returns momentum range.
640  """
641  return self.KeywordDictionaryKeywordDictionary['MomentumRange'].split()
642 
643  def NickName(self):
644  """
645  Return decay NickName.
646  """
647  return self.KeywordDictionaryKeywordDictionary['NickName'].replace(' ', '')
648 
649  def Date(self):
650  """
651  Return date.
652  """
653  return self.KeywordDictionaryKeywordDictionary['Date']
654 
655  def PhysicsWG(self):
656  """
657  Return mode WG.
658  """
659  return self.KeywordDictionaryKeywordDictionary['PhysicsWG']
660 
661  def DecayName(self):
662  """
663  Return decay name string.
664  """
665  return os.path.splitext(os.path.split(self.DecayFileNameDecayFileName)[1])[0]
666 
667  def Sample(self):
668  """
669  Check if overriden.
670  """
671  if 'Sample' in self.KeywordDictionaryKeywordDictionary:
672  sample = self.KeywordDictionaryKeywordDictionary['Sample']
673  elif int(self.EventTypeNumberEventTypeNumber()[0]) in (1, 2, 3, 7):
674  if int(self.EventTypeNumberEventTypeNumber()[1]) in (0, 9):
675  sample = 'Inclusive'
676  elif int(self.EventTypeNumberEventTypeNumber()[0]) == 1 and int(self.EventTypeNumberEventTypeNumber()[1]) in (1, 2, 3, 6, 7):
677  sample = 'Signal'
678  else:
679  sample = 'otherTreatment'
680  return sample
681 
682  def Production(self):
683  """
684  Checks for production algorithm.
685  """
686  production = 'Pythia'
687  if 'Production' in self.KeywordDictionaryKeywordDictionary:
688  production = self.KeywordDictionaryKeywordDictionary['Production']
689  return production
690 
691  def HeaderOptions(self):
692  """
693  Write the header of the options file.
694  """
695 
696  self.OptionFileOptionFile.WriteHeader(self.EventTypeNumberEventTypeNumber(),
697  self.DecayDescriptorDecayDescriptor())
698 
699 
700 def writeBkkTable(evttypeid, descriptor, nickname):
701  """
702  Write the file to create the entry in the ORACLE database.
703  """
704 
705  global bkk_first, eventid_inbkk
706  TableName = '../doc/table_event.txt'.format(os.environ['DECFILESROOT'])
707  logging.warning(TableName)
708  if bkk_first:
709  bkk_first = False
710  if not os.path.exists(TableName):
711  with open(TableName, 'wb') as f:
712  line = 'EventTypeID | NickName | Description\n'
713  f.write(line)
714  else:
715  # read the file
716  with open(TableName, 'rb') as f:
717  for line in f:
718  eventid_inbkk.append(line.split()[0])
719 
720  if evttypeid not in eventid_inbkk:
721  eventid_inbkk.append(evttypeid)
722  nick = nickname[:255]
723  desc = descriptor[:255]
724  with open(TableName, 'a+') as f:
725  line = '{0} | {1} | {2}\n'.format(evttypeid, nick, desc)
726  f.write(line)
727 
728 
729 def writeSQLTable(evttypeid, descriptor, nickname):
730  """
731  Write the file to create the entry in the database.
732  """
733 
734  global sql_first, eventid_insql
735  TableName = '../doc/table_event.sql'.format(os.environ['DECFILESROOT'])
736 
737  if sql_first:
738  sql_first = False
739  if not os.path.exists(TableName):
740  os.system('touch ' + TableName)
741  else:
742  # read the file
743  with open(TableName, 'rb') as f:
744  for line in f:
745  eventid_insql.append(line.split()[2].strip(','))
746 
747  if evttypeid not in eventid_insql:
748  eventid_insql.append(evttypeid)
749  nick = nickname[:255]
750  desc = descriptor[:255]
751  with open(TableName, 'a+') as f:
752  line = 'EVTTYPEID = {0}, DESCRIPTION = "{1}", PRIMARY = "{2}"\n'.format(
753  evttypeid, nick, desc)
754  f.write(line)
755 
756 
757 def readObsoleteTypeTable():
758  """
759  Read the table of obsolete events.
760  """
761 
762  filename = 'doc/table_obsolete.sql'.format(os.environ['DECFILESROOT'])
763  global list_of_obsoletes
764  try:
765  with open(filename, 'rb') as f:
766  for line in f:
767  list_of_obsoletes.append(line.split()[2].strip(','))
768  logging.info(' This will be ignored %s', line)
769  except IOError:
770  logging.warning('No files containing obsolete event types found')
771  except IndexError:
772  pass
773 
774 
775 def run_create(dkfile, remove, python, force):
776  """
777  Create an options file corresponding to a single decay file.
778  """
779 
780  technology = 'Text'
781  if python:
782  technology = 'Python'
783 
784  eventtype = EventType(dkfile, remove, technology)
785  eventtype.DecodeDecayFile()
786 
787  logging.info('Creation of production script file for Decay file %s.dec',
788  eventtype.DecayName())
789  try:
790  eventtype.Validate(list_of_obsoletes)
791  except SyntaxWarning:
792  if force:
793  pass
794  else:
795  raise UserWarning
796 
797  # check if the options file already exist and do not overwrite it
798  eventtype.SetOptionFileName()
799 
800  # get the first digit of the eventtype
801  AB = eventtype.EventTypeNumber()[0:2]
802  ABX = eventtype.EventTypeNumber()[0:2] + eventtype.E()
803  ABU = eventtype.EventTypeNumber()[0:2] + eventtype.U()
804 
805  eventtype.HeaderOptions()
806 
807  # Optional lines for all event types ---------------------------------
808  # Check if exists ExtraOptions keyword
809  if eventtype.HasExtraOptions():
810  eventtype.OptionFile.AddExtraOptions(eventtype)
811 
812  # Mandatory lines to write -------------------------------------------
813  # Event type number
814  eventtype.OptionFile.AddEventTypeNumber(eventtype)
815 
816  # Decay tool
817  if not eventtype.HasDecayEngine():
818  eventtype.OptionFile.AddEvtGenUserDecayFile(eventtype)
819  else:
820  eventtype.OptionFile.AddDecayEngine(eventtype)
821 
822  # Generation.SAMPLE.GENERATOR.InclusivePIDList
823  # if Inclusive
824  if 'Inclusive' in eventtype.Sample():
825  if eventtype.G() == '1':
826  pidlist = '521, -521, 511, -511, 531, -531, 541, -541, 5122, -5122, 5222, -5222, 5212, -5212, 5112, -5112, ' \
827  '5312, -5312, 5322, -5322, 5332, -5332, 5132, -5132, 5232, -5232'
828  elif int(eventtype.G()) in (2, 7):
829  pidlist = '421, -421, 411, -411, 431, -431, 4122, -4122, 443, 4112, -4112, 4212, -4212, 4222, -4222, 4312, ' \
830  '-4312, 4322, -4322, 4332, -4332, 4132, -4132, 4232, -4232, 100443, 441, 10441, 20443, 445, 4214, -4214, ' \
831  '4224, -4224, 4314, -4314, 4324, -4324, 4334, -4334, 4412, -4412, 4414,-4414, 4422, -4422, 4424, -4424, 4432, ' \
832  '-4432, 4434, -4434, 4444, -4444, 14122, -14122, 14124, -14124, 100441'
833  eventtype.OptionFile.AddInclusivePIDList(eventtype, pidlist)
834  else:
835  # if Type Signal
836  listing = { # tau
837  # Sigma
838  # Lambda
839  # Ks
840  # Xi
841  # Omega
842  '10': '521, -521, 511, -511, 531, -531, 541, -541, 5122, -5122, 5222, -5222, 5212, -5212, 5112, -5112, 5312, -5312, '
843  '5322, -5322, 5332, -5332, 5132, -5132, 5232, -5232',
844  '11': '511,-511',
845  '12': '521,-521',
846  '13': '531,-531',
847  '14': '541,-541',
848  '15': '5122,-5122',
849  '19': '521, -521, 511, -511, 531, -531, 541, -541, 5122, -5122, 5332, -5332, 5132, -5132, 5232, -5232',
850  '20': '421, -421, 411, -411, 431, -431, 4122, -4122, 443, 4112, -4112, 4212, -4212, 4222, -4222, 4312, -4312, 4322, '
851  '-4322, 4332, -4332, 4132, -4132, 4232, -4232, 100443, 441, 10441, 20443, 445, 4214, -4214, 4224, -4224, 4314, '
852  '-4314, 4324, -4324, 4334, -4334, 4412, -4412, 4414,-4414, 4422, -4422, 4424, -4424, 4432, -4432, 4434, -4434, '
853  '4444, -4444, 14122, -14122, 14124, -14124, 100441',
854  '21': '411,-411',
855  '22': '421,-421',
856  '23': '431,-431',
857  '24': '443',
858  '25': '4122,-4122',
859  '31': '15,-15',
860  '32': '3222,-3222',
861  '33': '3122,-3122',
862  '34': '310',
863  '35': '3312,-3312',
864  '36': '3334,-3334',
865  '70': '421, -421, 411, -411, 431, -431, 4122, -4122, 443, 4112, -4112, 4212, -4212, 4222, -4222, 4312, -4312, 4322, '
866  '-4322, 4332, -4332, 4132, -4132, 4232, -4232, 100443, 441, 10441, 20443, 445, 4214, -4214, 4224, -4224, 4314, '
867  '-4314, 4324, -4324, 4334, -4334, 4412, -4412, 4414,-4414, 4422, -4422, 4424, -4424, 4432, -4432, 4434, -4434, '
868  '4444, -4444, 14122, -14122, 14124, -14124, 100441',
869  '71': '411,-411',
870  '72': '421,-421',
871  '73': '431,-431',
872  '74': '443',
873  '75': '4122,-4122',
874  }
875  listingExcited = {
876  '270': '413,-413',
877  '271': '423,-423',
878  '272': '433,-433',
879  '273': '435,-435',
880  '274': '425,-425',
881  '275': '415,-415',
882  '276': '10433,-10433',
883  '277': '413,-413',
884  '770': '413,-413',
885  '771': '423,-423',
886  '772': '433,-433',
887  '280': '100443',
888  '281': '9920443',
889  '282': '10443',
890  '283': '10441',
891  '284': '20443',
892  '285': '445',
893  '286': '441',
894  '287': '30443',
895  '180': '553',
896  '181': '100553',
897  '182': '200553',
898  '183': '300553',
899  '184': '9000553',
900  '185': '10551',
901  '186': '20553',
902  '187': '555',
903  '160': '5112,-5112',
904  '161': '5212,-5212',
905  '162': '5222,-5222',
906  '163': '5132,-5132',
907  '164': '5232,-5232',
908  '165': '5332,-5332',
909  '170': '513,-513',
910  '171': '523,-523',
911  '172': '533,-533',
912  '173': '10513,-10513',
913  '174': '10523,-10523',
914  '175': '10533,-10533',
915  '176': '515,-515',
916  '177': '525,-525',
917  '178': '535,-535',
918  }
919 
920  # Check if exists ParticleTable keyword
921  if eventtype.HasParticleTable():
922  eventtype.OptionFile.AddParticleTable(eventtype)
923 
924  # Check if exists ParticleValue keyword
925  if eventtype.HasParticleValue():
926  eventtype.OptionFile.AddParticleValue(eventtype)
927 
928  # insert python lines directly
929  if technology == 'Python':
930  if eventtype.HasPythonCodeToInsert():
931  eventtype.OptionFile.Write([eventtype.PythonCodeToInsert()])
932 
933  writeBkkTable(eventtype.EventTypeNumber(), eventtype.DecayDescriptor(),
934  eventtype.NickName())
935  writeSQLTable(eventtype.EventTypeNumber(), eventtype.DecayDescriptor(),
936  eventtype.NickName())
937 
938 
939 def run_loop(remove, python, force):
940  """
941  Loop in the FILES directory to generate the options file.
942  """
943 
944  files = glob.glob(os.environ['DECFILESROOT'] + '/dec/*.dec')
945  for f in files:
946  try:
947  run_create(f, remove, python, force)
948  except UserWarning:
949  pass
950 
951 
952 def CheckFile(option, opt_str, value, parser):
953  """
954  Check if file exists.
955  """
956 
957  if not os.path.exists('{0}/dec/{1}.dec'.format(os.environ['DECFILESROOT'],
958  value)):
959  raise OptionValueError('Decay file %s.dec ' % value + 'does not ' +
960  'exist in the $DECFILESROOT/dec directory')
961  setattr(parser.values, option.dest, value)
962 
963 
964 # ---------------------------------------------------------------------------
965 # Color formatting
966 # ---------------------------------------------------------------------------
967 
968 (
969  BLACK,
970  RED,
971  GREEN,
972  YELLOW,
973  BLUE,
974  MAGENTA,
975  CYAN,
976  WHITE,
977 ) = list(range(8))
978 
979 # The background is set with 40 plus the number of the color, and the
980 # foreground with 30
981 
982 # These are the sequences need to get colored ouput
983 RESET_SEQ = "\033[0m"
984 COLOR_SEQ = "\033[1;%d;40m"
985 BOLD_SEQ = "\033[1m"
986 
987 COLORS = {
988  'WARNING': YELLOW,
989  'INFO': WHITE,
990  'DEBUG': BLUE,
991  'CRITICAL': YELLOW,
992  'ERROR': RED,
993 }
994 
995 
996 class ColoredFormatter(logging.Formatter):
997 
998  """
999  Define color convention for output messages.
1000  """
1001 
1002  def __init__(self, msg, use_color=True):
1003  """
1004  Constructor.
1005 
1006  Attributes:
1007  use_color use color output flag
1008  """
1009  logging.Formatter.__init__(self, msg)
1010 
1011 
1012  self.use_coloruse_color = use_color
1013 
1014  def format(self, record):
1015  """
1016  Set output format.
1017  """
1018  levelname = record.levelname
1019  color = COLOR_SEQ % (30 + COLORS[levelname])
1020  message = logging.Formatter.format(self, record)
1021  message = message.replace(
1022  '$RESET',
1023  RESET_SEQ).replace(
1024  '$BOLD',
1025  BOLD_SEQ).replace(
1026  '$COLOR',
1027  color)
1028  return message + RESET_SEQ
1029 
1030 
1031 # ---------------------------------------------------------------------------
1032 # Main routine
1033 # ---------------------------------------------------------------------------
1034 
1035 def main():
1036  global exit_status
1037 
1038  mylog = logging.StreamHandler()
1039  logging.getLogger().setLevel(logging.DEBUG)
1040  mylog.setFormatter(
1042  '$COLOR$BOLD[%(levelname)-10s]$RESET$COLOR %(message)s',
1043  True))
1044  logging.getLogger().addHandler(mylog)
1045  usage = 'usage: %prog [options]'
1046  parser = OptionParser(usage=usage, version=version)
1047  parser.add_option(
1048  '-q',
1049  '--quiet',
1050  dest='verbose',
1051  default=False,
1052  action='store_false',
1053  help='switch off info printout',
1054  )
1055  parser.add_option('--remove', dest='remove', default=False,
1056  action='store_true',
1057  help='force the delete of the option file before '
1058  'creating a new one, by default existing option '
1059  'files are not overwritten')
1060  parser.add_option(
1061  '-d',
1062  '--decay',
1063  type='string',
1064  dest='NickName',
1065  help='name of the nick name of the decay to create option '
1066  'for, if not specified, loop over all decay files in the '
1067  'dec directory',
1068  action='callback',
1069  callback=CheckFile,
1070  )
1071  parser.add_option('--text', dest='python', default=True,
1072  action='store_false',
1073  help='create text option files instead of python options'
1074  )
1075  parser.add_option(
1076  '--force',
1077  dest='force',
1078  default=False,
1079  action='store_true',
1080  help='force create of option file even when the decay file '
1081  'syntax is not correct')
1082 
1083  # Check that the environment variable DECFILESROOT exist otherwise
1084  # set it to ../dec
1085  if 'DECFILESROOT' not in os.environ:
1086  logging.warning('')
1087  logging.warning('The variable DECFILESROOT is not defined.')
1088  logging.warning('Use ../ instead.')
1089  logging.warning(
1090  'Run the setup script of the package to set the correct value.')
1091  logging.warning('')
1092  os.environ['DECFILESROOT'] = '../'
1093  else:
1094  logging.info('')
1095  logging.info('The DECFILESROOT environment variable is set to: %s',
1096  os.environ['DECFILESROOT'])
1097  logging.info('')
1098 
1099  (options, args) = parser.parse_args()
1100 
1101  if not options.verbose:
1102  logging.getLogger().setLevel(logging.INFO)
1103 
1104  readObsoleteTypeTable()
1105 
1106  if options.NickName:
1107  try:
1108  run_create(
1109  '{0}/dec/{1}.dec'.format(
1110  os.environ['DECFILESROOT'],
1111  options.NickName),
1112  options.remove,
1113  options.python,
1114  options.force)
1115  except UserWarning:
1116  exit_status = 1
1117  else:
1118  run_loop(options.remove, options.python, options.force)
1119 
1120 
1121 if __name__ == '__main__':
1122  main()
1123  sys.exit(exit_status)
def __init__(self, msg, use_color=True)
def __init__(self, filename, remove, technology)
list MandatoryKeywords
list of mandatory keywords for file description
technology
specify the langauge of the script
OptionFile
flag for existence of option file
list OptionalKeywords
list of optional keywords for file description
def SetOptionFileName(self, filename=None)
KeywordDictionary
dictionary of keywords
def Validate(self, obsoletes)
def WriteHeader(self, eventtype, descriptor)
def AddEvtGenUserDecayFile(self, eventtype)
f
alternative name of the file
def IncreaseOptionValue(self, option, value)
def AddOptionValue(self, option, value, substitute=False)
def IncreaseOptionValue(self, option, value)
def AddOptionValue(self, option, value, substitute=False)
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:75