1
################################################################################
3
# Copyright (c) 2011 The MadGraph Development team and Contributors
5
# This file is a part of the MadGraph 5 project, an application which
6
# automatically generates Feynman diagrams and matrix elements for arbitrary
7
# high-energy processes in the Standard Model and beyond.
9
# It is subject to the MadGraph license which should accompany this
12
# For more information, please visit: http://madgraph.phys.ucl.ac.be
14
################################################################################
15
"""A File for splitting"""
24
import madgraph.various.misc as misc
25
import madgraph.iolibs.file_writers as file_writers
26
import models.check_param_card as param_card_reader
27
from madgraph import MG5DIR
31
import internal.file_writers as file_writers
32
import internal.check_param_card as param_card_reader
33
MEDIR = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
34
MEDIR = os.path.split(MEDIR)[0]
38
logger = logging.getLogger('madevent.cards')
44
ordered_items = ['mgversion', 'mg5proccard', 'mgproccard', 'mgruncard',
45
'slha', 'MGGenerationInfo', 'mgpythiacard', 'mgpgscard',
46
'mgdelphescard', 'mgdelphestrigger']
48
def __init__(self, banner_path=None):
54
self['mgversion'] = '#%s\n' % open(pjoin(MEDIR, 'MGMEVersion.txt')).read()
56
info = misc.get_pkg_info()
57
self['mgversion'] = info['version']+'\n'
60
self.read_banner(banner_path)
62
############################################################################
64
############################################################################
65
pat_begin=re.compile('<(?P<name>\w*)>')
66
pat_end=re.compile('</(?P<name>\w*)>')
68
tag_to_file={'slha':'param_card.dat',
69
'mgruncard':'run_card.dat',
70
'mgpythiacard':'pythia_card.dat',
71
'mgpgscard' : 'pgs_card.dat',
72
'mgdelphescard':'delphes_card.dat',
73
'mgdelphestrigger':'delphes_trigger.dat',
74
'mg5proccard':'proc_card_mg5.dat',
75
'mgproccard': 'proc_card.dat',
77
'mggenerationinfo':'',
78
'montecarlomasses':'',
79
'madspin':'madspin_card.dat'
82
def read_banner(self, input_path):
85
if isinstance(input_path, str):
86
input_path = open(input_path)
90
for line in input_path:
91
if self.pat_begin.search(line):
92
tag = self.pat_begin.search(line).group('name').lower()
93
if tag in self.tag_to_file:
96
if store and self.pat_end.search(line):
97
if tag == self.pat_end.search(line).group('name').lower():
104
#reaching end of the banner in a event file avoid to read full file
105
if "</init>" in line:
107
elif "<event>" in line:
110
def load_basic(self, medir):
111
""" Load the proc_card /param_card and run_card """
113
self.add(pjoin(medir,'Cards', 'param_card.dat'))
114
self.add(pjoin(medir,'Cards', 'run_card.dat'))
115
if os.path.exists(pjoin(medir, 'SubProcesses', 'procdef_mg5.dat')):
116
self.add(pjoin(medir,'SubProcesses', 'procdef_mg5.dat'))
117
self.add(pjoin(medir,'Cards', 'proc_card_mg5.dat'))
119
self.add(pjoin(medir,'Cards', 'proc_card.dat'))
122
def change_seed(self, seed):
123
"""Change the seed value in the banner"""
125
p = re.compile(r'''^\s*\d+\s*=\s*iseed''', re.M)
126
new_seed_str = " %s = iseed" % seed
127
self['mgruncard'] = p.sub(new_seed_str, self['mgruncard'])
129
def add_generation_info(self, cross, nb_event):
130
"""add info on MGGeneration"""
133
# Number of Events : %s
134
# Integrated weight (pb) : %s
135
""" % (nb_event, cross)
136
self['MGGenerationInfo'] = text
138
############################################################################
140
############################################################################
141
def split(self, me_dir, proc_card=True):
142
"""write the banner in the Cards directory.
143
proc_card argument is present to avoid the overwrite of proc_card
146
for tag, text in self.items():
147
if tag == 'mgversion':
149
if not proc_card and tag in ['mg5proccard','mgproccard']:
151
if not self.tag_to_file[tag]:
153
ff = open(pjoin(me_dir, 'Cards', self.tag_to_file[tag]), 'w')
157
############################################################################
159
############################################################################
160
def check_pid(self, pid2label):
161
"""special routine removing width/mass of particles not present in the model
162
This is usefull in case of loop model card, when we want to use the non
165
if not hasattr(self, 'param_card'):
166
self.charge_card('slha')
168
for tag in ['mass', 'decay']:
169
block = self.param_card.get(tag)
171
pid = data.lhacode[0]
172
if pid not in pid2label.keys():
175
############################################################################
177
############################################################################
178
def write(self, output_path, close_tag=True):
179
"""write the banner"""
181
if isinstance(output_path, str):
182
ff = open(output_path, 'w')
187
header = open(pjoin(MEDIR, 'Source', 'banner_header.txt')).read()
189
header = open(pjoin(MG5DIR,'Template', 'LO', 'Source', 'banner_header.txt')).read()
194
for tag in [t for t in self.ordered_items if t in self.keys()]:
195
ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \
196
{'tag':tag, 'text':self[tag].strip()})
197
for tag in [t for t in self.keys() if t not in self.ordered_items]:
200
ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \
201
{'tag':tag, 'text':self[tag].strip()})
203
ff.write('</header>\n')
207
ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \
208
{'tag':'init', 'text':text.strip()})
210
ff.write('</LesHouchesEvents>\n')
213
############################################################################
215
############################################################################
216
def add(self, path, tag=None):
217
"""Add the content of the file to the banner"""
220
card_name = os.path.basename(path)
221
if 'param_card' in card_name:
223
elif 'run_card' in card_name:
225
elif 'pythia_card' in card_name:
227
elif 'pgs_card' in card_name:
229
elif 'delphes_card' in card_name:
230
tag = 'MGDelphesCard'
231
elif 'delphes_trigger' in card_name:
232
tag = 'MGDelphesTrigger'
233
elif 'proc_card_mg5' in card_name:
235
elif 'proc_card' in card_name:
237
elif 'procdef_mg5' in card_name:
240
raise Exception, 'Impossible to know the type of the card'
242
self.add_text(tag.lower(), open(path).read())
244
def add_text(self, tag, text):
245
"""Add the content of the file to the banner"""
247
self[tag.lower()] = text
250
def charge_card(self, tag):
251
"""Build the python object associated to the card"""
253
if tag == 'param_card':
255
elif tag == 'run_card':
257
elif tag == 'proc_card':
260
assert tag in ['slha', 'mgruncard', 'mg5proccard'], 'invalid card %s' % tag
263
param_card = self[tag].split('\n')
264
self.param_card = param_card_reader.ParamCard(param_card)
265
return self.param_card
266
elif tag == 'mgruncard':
267
run_card = self[tag].split('\n')
268
if 'parton_shower' in self[tag]:
269
self.run_card = RunCardNLO(run_card)
271
self.run_card = RunCard(run_card)
273
elif tag == 'mg5proccard':
274
proc_card = self[tag].split('\n')
275
self.proc_card = ProcCard(proc_card)
276
return self.proc_card
279
def get_detail(self, tag, *arg):
280
"""return a specific """
282
if tag == 'param_card':
284
attr_tag = 'param_card'
285
elif tag == 'run_card':
287
attr_tag = 'run_card'
288
elif tag == 'proc_card':
290
attr_tag = 'proc_card'
293
attr_tag = 'proc_card'
295
elif tag == 'generate':
297
attr_tag = 'proc_card'
299
assert tag in ['slha', 'mgruncard', 'mg5proccard'], 'not recognized'
301
if not hasattr(self, attr_tag):
302
self.charge_card(attr_tag)
304
card = getattr(self, attr_tag)
306
if tag == 'mg5proccard':
307
return card.info[arg[0]]
309
elif len(arg) == 2 and tag == 'slha':
310
return card[arg[0]].get(arg[1:])
312
raise Exception, "Unknow command"
317
def split_banner(banner_path, me_dir, proc_card=True):
318
"""a simple way to split a banner"""
320
banner = Banner(banner_path)
321
banner.split(me_dir, proc_card)
323
def recover_banner(results_object, level):
324
"""as input we receive a gen_crossxhtml.AllResults object.
325
This define the current banner and load it
328
run = results_object.current['run_name']
329
tag = results_object.current['tag']
332
path = results_object.path
333
banner_path = pjoin(path,'Events',run,'%s_%s_banner.txt' % (run, tag))
335
if not os.path.exists(banner_path):
336
# security if the banner was remove (or program canceled before created it)
339
banner = Banner(banner_path)
343
if level == 'pythia':
344
if 'mgpythiacard' in banner:
345
del banner['mgpythiacard']
346
if level in ['pythia','pgs','delphes']:
347
for tag in ['mgpgscard', 'mgdelphescard', 'mgdelphestrigger']:
354
"""A class object for the run_card"""
356
def __init__(self, run_card):
359
if isinstance(run_card, str):
360
run_card = file(run_card,'r')
362
pass # use in banner loading
364
for line in run_card:
365
line = line.split('#')[0]
366
line = line.split('!')[0]
367
line = line.split('=')
370
self[line[1].strip()] = line[0].replace('\'','').strip()
372
def get_default(self, name, default, log_level):
373
"""return self[name] if exist otherwise default. log control if we
374
put a warning or not if we use the default value"""
380
logger.log(log_level, 'run_card missed argument %s. Takes default: %s'
386
def format(format, value):
387
"""format the value"""
390
if str(value) in ['1','T','.true.','True']:
395
elif format == 'int':
396
return str(int(value))
398
elif format == 'float':
399
if isinstance(value, str):
400
value = value.replace('d','e')
401
return ('%.10e' % float(value)).replace('e','d')
403
elif format == 'str':
404
return "'%s'" % value
408
def write(self, output_file, template=None):
409
"""Write the run_card in output_file according to template
410
(a path to a valid run_card)"""
413
template = output_file
416
for line in file(template,'r'):
417
nline = line.split('#')[0]
418
nline = nline.split('!')[0]
419
comment = line[len(nline):]
420
nline = nline.split('=')
424
text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment)
426
fsock = open(output_file,'w')
431
def write_include_file(self, output_path):
432
"""writing the run_card.inc file"""
434
self.fsock = file_writers.FortranWriter(output_path)
435
################################################################################
436
# Writing the lines corresponding to the cuts
437
################################################################################
439
self.add_line('maxjetflavor', 'int', 4)
440
self.add_line('auto_ptj_mjj', 'bool', True)
441
self.add_line('cut_decays', 'bool', True)
443
self.add_line('ptj', 'float', 20)
444
self.add_line('ptb', 'float', 20)
445
self.add_line('pta', 'float', 20)
446
self.add_line('ptl', 'float', 20)
447
self.add_line('misset', 'float', 0)
448
self.add_line('ptonium', 'float', 0.0)
450
self.add_line('ptjmax', 'float', -1)
451
self.add_line('ptbmax', 'float', -1)
452
self.add_line('ptamax', 'float', -1)
453
self.add_line('ptlmax', 'float', -1)
454
self.add_line('missetmax', 'float', -1)
455
# maximal rapidity (absolute value)
456
self.add_line('etaj', 'float', 4.0)
457
self.add_line('etab', 'float', 4.0)
458
self.add_line('etaa', 'float', 4.0)
459
self.add_line('etal', 'float', 4.0)
460
# minimal rapidity (absolute value)
461
self.add_line('etajmin', 'float', 0.0)
462
self.add_line('etabmin', 'float', 0.0)
463
self.add_line('etaamin', 'float', 0.0)
464
self.add_line('etalmin', 'float', 0.0)
465
self.add_line('etaonium', 'float', 100.0)
467
self.add_line('ej', 'float', 0.0)
468
self.add_line('eb', 'float', 0.0)
469
self.add_line('ea', 'float', 0.0)
470
self.add_line('el', 'float', 0.0)
472
self.add_line('ejmax', 'float', -1)
473
self.add_line('ebmax', 'float', -1)
474
self.add_line('eamax', 'float', -1)
475
self.add_line('elmax', 'float', -1)
477
self.add_line('drjj', 'float', 0.4)
478
self.add_line('drbb', 'float', 0.4)
479
self.add_line('drll', 'float', 0.4)
480
self.add_line('draa', 'float', 0.4)
481
self.add_line('drbj', 'float', 0.4)
482
self.add_line('draj', 'float', 0.4)
483
self.add_line('drjl', 'float', 0.4)
484
self.add_line('drab', 'float', 0.4)
485
self.add_line('drbl', 'float', 0.4)
486
self.add_line('dral', 'float', 0.4)
488
self.add_line('drjjmax', 'float', -1)
489
self.add_line('drbbmax', 'float', -1)
490
self.add_line('drllmax', 'float', -1)
491
self.add_line('draamax', 'float', -1)
492
self.add_line('drbjmax', 'float', -1)
493
self.add_line('drajmax', 'float', -1)
494
self.add_line('drjlmax', 'float', -1)
495
self.add_line('drabmax', 'float', -1)
496
self.add_line('drblmax', 'float', -1)
497
self.add_line('dralmax', 'float', -1)
498
# minimum invariant mass for pairs
499
self.add_line('mmjj', 'float', 0.0)
500
self.add_line('mmbb', 'float', 0.0)
501
self.add_line('mmaa', 'float', 0.0)
502
self.add_line('mmll', 'float', 0.0)
503
# maximum invariant mall for pairs
504
self.add_line('mmjjmax', 'float', -1)
505
self.add_line('mmbbmax', 'float', -1)
506
self.add_line('mmaamax', 'float', -1)
507
self.add_line('mmllmax', 'float', -1)
508
#Min Maxi invariant mass for all leptons
509
self.add_line("mmnl", 'float', 0.0)
510
self.add_line("mmnlmax", 'float', -1)
512
self.add_line("xptj", 'float', 0.0)
513
self.add_line("xptb", 'float', 0.0)
514
self.add_line("xpta", 'float', 0.0)
515
self.add_line("xptl", 'float', 0.0)
516
self.add_line("xmtcentral", 'float', 0.0, fortran_name='xmtc', log=10)
518
self.add_line("xetamin", 'float', 0.0)
519
self.add_line("deltaeta", 'float', 0.0)
521
self.add_line("xqcut", 'float', 0.0)
522
self.add_line("d", 'float', 1.0, log=10)
523
# Set min pt of one heavy particle
524
self.add_line("ptheavy", 'float', 0.0)
525
# Pt of pairs of leptons (CHARGED AND NEUTRALS)
526
self.add_line("ptllmin", "float", 0.0)
527
self.add_line("ptllmax", "float", -1)
528
# Check the pt's of the jets sorted by pt
529
self.add_line("ptj1min", "float", 0.0)
530
self.add_line("ptj1max", "float", -1)
531
self.add_line("ptj2min", "float", 0.0)
532
self.add_line("ptj2max", "float", -1)
533
self.add_line("ptj3min", "float", 0.0)
534
self.add_line("ptj3max", "float", -1)
535
self.add_line("ptj4min", "float", 0.0)
536
self.add_line("ptj4max", "float", -1)
537
self.add_line("cutuse", "float", 0.0)
538
# Check the pt's of leptons sorted by pt
539
self.add_line("ptl1min", "float", 0.0)
540
self.add_line("ptl1max", "float", -1)
541
self.add_line("ptl2min", "float", 0.0)
542
self.add_line("ptl2max", "float", -1)
543
self.add_line("ptl3min", "float", 0.0)
544
self.add_line("ptl3max", "float", -1)
545
self.add_line("ptl4min", "float", 0.0)
546
self.add_line("ptl4max", "float", -1)
548
self.add_line("ht2min", 'float', 0.0)
549
self.add_line("ht3min", 'float', 0.0)
550
self.add_line("ht4min", 'float', 0.0)
551
self.add_line("ht2max", 'float', -1)
552
self.add_line("ht3max", 'float', -1)
553
self.add_line("ht4max", 'float', -1)
554
self.add_line("htjmin", 'float', 0.0)
555
self.add_line("htjmax", 'float', -1)
556
self.add_line("ihtmin", 'float', 0.0)
557
self.add_line("ihtmax", 'float', -1)
559
################################################################################
560
# Writing the lines corresponding to anything but cuts
561
################################################################################
563
self.add_line("gridpack","bool", False)
564
self.add_line("gridrun",'bool', False, log=10)
565
if str(self['gridrun']) in ['1','T','.true','True'] and \
566
str(self['gridpack']) in ['1','T','.true','True']:
567
self.add_line('gseed', 'int', 0, fortran_name='iseed')
569
self.add_line('iseed', 'int', 0, fortran_name='iseed')
570
# Renormalizrion and factorization scales
571
self.add_line('fixed_ren_scale', 'bool', True)
572
self.add_line('fixed_fac_scale', 'bool', True)
573
self.add_line('scale', 'float', 'float', 91.188)
574
self.add_line('dsqrt_q2fact1','float', 91.188, fortran_name='sf1')
575
self.add_line('dsqrt_q2fact2', 'float', 91.188, fortran_name='sf2')
576
self.add_line('scalefact', 'float', 1.0)
577
self.add_line('fixed_couplings', 'bool', True, log=10)
578
self.add_line('ickkw', 'int', 0)
579
self.add_line('chcluster', 'bool', False)
580
self.add_line('ktscheme', 'int', 1)
581
self.add_line('asrwgtflavor', 'int', 5)
582
if int(self['ickkw'])>0:
583
self.add_line('alpsfact', 'float', 1.0)
584
self.add_line('pdfwgt', 'bool', True)
585
if int(self['ickkw'])==2:
586
self.add_line('highestmult','int', 0, fortran_name='nhmult')
587
self.add_line('issgridfile','str','issudgrid.dat')
588
# Collider energy and type
589
self.add_line('lpp1', 'int', 1, fortran_name='lpp(1)')
590
self.add_line('lpp2', 'int', 1, fortran_name='lpp(2)')
591
self.add_line('ebeam1', 'float', 7000, fortran_name='ebeam(1)')
592
self.add_line('ebeam2', 'float', 7000, fortran_name='ebeam(2)')
594
self.add_line('polbeam1', 'float', 0.0, fortran_name='pb1')
595
self.add_line('polbeam2', 'float', 0.0, fortran_name='pb2')
596
# BW cutoff (M+/-bwcutoff*Gamma)
597
self.add_line('bwcutoff', 'float', 15.0)
599
self.add_line('pdlabel','str','cteq6l1')
600
if self['pdlabel'] == 'lhapdf':
601
self.add_line('lhaid', 'int', 10042)
603
self.add_line('lhaid', 'int', 10042, log=10)
610
def add_line(self, card_name, type, default, log=30, fortran_name=None):
611
"""get the line for the .inc file"""
613
value = self.get_default(card_name, default, log)
615
fortran_name = card_name
616
self.fsock.writelines(' %s = %s \n' % (fortran_name, self.format(type, value)))
619
class RunCardNLO(RunCard):
620
"""A class object for the run_card for a (aMC@)NLO pocess"""
623
def write_include_file(self, output_path):
624
"""writing the run_card.inc file"""
626
self.fsock = file_writers.FortranWriter(output_path)
627
################################################################################
628
# Writing the lines corresponding to the cuts
629
################################################################################
631
self.add_line('maxjetflavor', 'int', 5)
633
self.add_line('ptj', 'float', 20)
634
self.add_line('etaj', 'float', -1.0)
635
self.add_line('ptl', 'float', 20)
636
self.add_line('etal', 'float', -1.0)
638
self.add_line('drll', 'float', 0.4)
639
# minimum invariant mass for pairs
640
self.add_line('mll', 'float', 0.0)
643
self.add_line("jetradius", 'float', 0.7, log=10)
645
################################################################################
646
# Writing the lines corresponding to anything but cuts
647
################################################################################
649
self.add_line('iseed', 'int', 0)
650
self.add_line('parton_shower', 'str', 'HERWIG6', fortran_name='shower_mc')
651
self.add_line('nevents', 'int', 10000)
652
self.add_line('event_norm', 'str', 'average', fortran_name='event_norm')
653
# Renormalizrion and factorization scales
654
self.add_line('fixed_ren_scale', 'bool', True)
655
self.add_line('fixed_fac_scale', 'bool', True)
656
self.add_line('fixed_QES_scale', 'bool', True)
657
self.add_line('muR_ref_fixed', 'float', 91.188)
658
self.add_line('muF1_ref_fixed','float', 91.188)
659
self.add_line('muF2_ref_fixed', 'float', 91.188)
660
self.add_line('QES_ref_fixed', 'float', 91.188)
661
self.add_line('muR_over_ref', 'float', 1.0)
662
self.add_line('muF1_over_ref', 'float', 1.0)
663
self.add_line('muF2_over_ref', 'float', 1.0)
664
self.add_line('QES_over_ref', 'float', 1.0)
666
self.add_line('reweight_scale', 'bool', True, fortran_name='do_rwgt_scale')
667
self.add_line('rw_Rscale_up', 'float', 2.0)
668
self.add_line('rw_Rscale_down', 'float', 0.5)
669
self.add_line('rw_Fscale_up', 'float', 2.0)
670
self.add_line('rw_Fscale_down', 'float', 0.5)
671
self.add_line('reweight_PDF', 'bool', True, fortran_name='do_rwgt_pdf')
672
self.add_line('PDF_set_min', 'int', 21101)
673
self.add_line('PDF_set_max', 'int', 21140)
675
# self.add_line('fixed_couplings', 'bool', True, log=10)
676
self.add_line('jetalgo', 'int', 1)
677
# Collider energy and type
678
self.add_line('lpp1', 'int', 1, fortran_name='lpp(1)')
679
self.add_line('lpp2', 'int', 1, fortran_name='lpp(2)')
680
self.add_line('ebeam1', 'float', 4000, fortran_name='ebeam(1)')
681
self.add_line('ebeam2', 'float', 4000, fortran_name='ebeam(2)')
682
# BW cutoff (M+/-bwcutoff*Gamma)
683
self.add_line('bwcutoff', 'float', 15.0)
685
self.add_line('pdlabel','str','cteq6_m')
686
if self['pdlabel'] == 'lhapdf':
687
self.add_line('lhaid', 'int', 10042)
689
self.add_line('lhaid', 'int', 10042, log=10)
693
class ProcCard(list):
694
"""Basic Proccard object"""
696
def __init__(self, init=None):
697
""" initialize a basic proc_card"""
698
self.info = {'model': 'sm', 'generate':None,
699
'full_model_line':'import model sm'}
705
def read(self, init):
706
"""read the proc_card and save the information"""
708
if isinstance(init, str): #path to file
709
init = file(init, 'r')
714
def move_to_last(self, cmd):
715
"""move an element to the last history."""
717
if line.startswith(cmd):
719
list.append(self, line)
721
def append(self, line):
722
""""add a line in the proc_card perform automatically cleaning"""
729
list.append(self, line)
735
# Remove previous outputs from history
736
self.clean(allow_for_removal = ['output'], keep_switch=True,
737
remove_bef_last='output')
738
elif cmd == 'generate':
739
# Remove previous generations from history
740
self.clean(remove_bef_last='generate', keep_switch=True,
741
allow_for_removal= ['generate', 'add process', 'output'])
742
self.info['generate'] = ' '.join(cmds[1:])
743
elif cmd == 'import':
746
if cmds[1].startswith('model'):
747
self.info['full_model_line'] = line
748
self.clean(remove_bef_last='import', keep_switch=True,
749
allow_for_removal=['generate', 'add process', 'output'])
750
if cmds[1] == 'model':
751
self.info['model'] = cmds[2]
753
self.info['model'] = None # not UFO model
754
elif cmds[1] == 'proc_v4':
759
def clean(self, to_keep=['set','add','load'],
760
remove_bef_last=None,
761
to_remove=['open','display','launch', 'check','history'],
762
allow_for_removal=None,
764
"""Remove command in arguments from history.
765
All command before the last occurrence of 'remove_bef_last'
766
(including it) will be removed (but if another options tells the opposite).
767
'to_keep' is a set of line to always keep.
768
'to_remove' is a set of line to always remove (don't care about remove_bef_
769
status but keep_switch acts.).
770
if 'allow_for_removal' is define only the command in that list can be
771
remove of the history for older command that remove_bef_lb1. all parameter
772
present in to_remove are always remove even if they are not part of this
774
keep_switch force to keep the statement remove_bef_??? which changes starts
779
if __debug__ and allow_for_removal:
781
assert arg not in allow_for_removal
787
while nline > -len(self):
788
switch = False # set in True when removal pass in True
790
#check if we need to pass in removal mode
791
if not removal and remove_bef_last:
792
if self[nline].startswith(remove_bef_last):
796
# if this is the switch and is protected pass to the next element
797
if switch and keep_switch:
801
# remove command in to_remove (whatever the status of removal)
802
if any([self[nline].startswith(arg) for arg in to_remove]):
806
# Only if removal mode is active!
808
if allow_for_removal:
809
# Only a subset of command can be removed
810
if any([self[nline].startswith(arg)
811
for arg in allow_for_removal]):
814
elif not any([self[nline].startswith(arg) for arg in to_keep]):
815
# All command have to be remove but protected
819
# update the counter to pass to the next element
822
def __getattr__(self, tag):
823
if isinstance(tag, int):
824
list.__getattr__(self, tag)
826
return self.info[tag]